From b508728dc8d993a5b4ad5839b9553228b3ef4b47 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Tue, 26 Jul 2011 14:25:57 +0400 Subject: SONAR-2596,SONAR-2601 UI for email notifications * Add email configuration to sidebar menu * I18n for email and notifications settings * Email configuration properties must be secured * Rename sonar-email-plugin to sonar-email-notifications-plugin --- plugins/sonar-email-notifications-plugin/pom.xml | 63 ++++ .../emailnotifications/EmailConfiguration.java | 86 ++++++ .../EmailNotificationChannel.java | 190 ++++++++++++ .../EmailNotificationsPlugin.java | 42 +++ .../emailnotifications/api/EmailMessage.java | 115 +++++++ .../emailnotifications/api/EmailTemplate.java | 32 ++ .../reviews/ChangesInReviewAssignedToMe.java | 48 +++ .../reviews/ChangesInReviewCreatedByMe.java | 44 +++ .../reviews/ReviewEmailTemplate.java | 117 ++++++++ .../emailnotifications/EmailConfigurationTest.java | 53 ++++ .../EmailNotificationChannelTest.java | 182 ++++++++++++ .../EmailNotificationsPluginTest.java | 34 +++ .../reviews/ChangesInReviewAssignedToMeTest.java | 78 +++++ .../reviews/ChangesInReviewCreatedByMeTest.java | 74 +++++ .../reviews/ReviewEmailTemplateTest.java | 330 +++++++++++++++++++++ plugins/sonar-email-plugin/pom.xml | 63 ---- .../sonar/plugins/email/EmailConfiguration.java | 86 ------ .../plugins/email/EmailNotificationChannel.java | 190 ------------ .../java/org/sonar/plugins/email/EmailPlugin.java | 42 --- .../org/sonar/plugins/email/api/EmailMessage.java | 115 ------- .../org/sonar/plugins/email/api/EmailTemplate.java | 32 -- .../email/reviews/ChangesInReviewAssignedToMe.java | 48 --- .../email/reviews/ChangesInReviewCreatedByMe.java | 44 --- .../plugins/email/reviews/ReviewEmailTemplate.java | 117 -------- .../plugins/email/EmailConfigurationTest.java | 53 ---- .../email/EmailNotificationChannelTest.java | 182 ------------ .../org/sonar/plugins/email/EmailPluginTest.java | 34 --- .../reviews/ChangesInReviewAssignedToMeTest.java | 78 ----- .../reviews/ChangesInReviewCreatedByMeTest.java | 74 ----- .../email/reviews/ReviewEmailTemplateTest.java | 327 -------------------- .../main/resources/org/sonar/i18n/core.properties | 28 ++ pom.xml | 2 +- sonar-application/pom.xml | 2 +- sonar-server/pom.xml | 2 +- .../controllers/email_configuration_controller.rb | 7 +- .../WEB-INF/app/views/account/index.html.erb | 26 +- .../app/views/email_configuration/index.html.erb | 36 ++- .../WEB-INF/app/views/layouts/_layout.html.erb | 1 + 38 files changed, 1557 insertions(+), 1520 deletions(-) create mode 100644 plugins/sonar-email-notifications-plugin/pom.xml create mode 100644 plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailConfiguration.java create mode 100644 plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationChannel.java create mode 100644 plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java create mode 100644 plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/api/EmailMessage.java create mode 100644 plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/api/EmailTemplate.java create mode 100644 plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewAssignedToMe.java create mode 100644 plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewCreatedByMe.java create mode 100644 plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ReviewEmailTemplate.java create mode 100644 plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailConfigurationTest.java create mode 100644 plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationChannelTest.java create mode 100644 plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationsPluginTest.java create mode 100644 plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewAssignedToMeTest.java create mode 100644 plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewCreatedByMeTest.java create mode 100644 plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ReviewEmailTemplateTest.java delete mode 100644 plugins/sonar-email-plugin/pom.xml delete mode 100644 plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailConfiguration.java delete mode 100644 plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailNotificationChannel.java delete mode 100644 plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailPlugin.java delete mode 100644 plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/api/EmailMessage.java delete mode 100644 plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/api/EmailTemplate.java delete mode 100644 plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ChangesInReviewAssignedToMe.java delete mode 100644 plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ChangesInReviewCreatedByMe.java delete mode 100644 plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ReviewEmailTemplate.java delete mode 100644 plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailConfigurationTest.java delete mode 100644 plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailNotificationChannelTest.java delete mode 100644 plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailPluginTest.java delete mode 100644 plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ChangesInReviewAssignedToMeTest.java delete mode 100644 plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ChangesInReviewCreatedByMeTest.java delete mode 100644 plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ReviewEmailTemplateTest.java diff --git a/plugins/sonar-email-notifications-plugin/pom.xml b/plugins/sonar-email-notifications-plugin/pom.xml new file mode 100644 index 00000000000..181e56b59e3 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + + org.codehaus.sonar + sonar + 2.10-SNAPSHOT + ../.. + + + org.codehaus.sonar.plugins + sonar-email-notifications-plugin + sonar-plugin + + Sonar :: Plugins :: Email Notifications + Email Notifications + + + + org.codehaus.sonar + sonar-plugin-api + provided + + + org.codehaus.sonar + sonar-core + provided + + + org.apache.commons + commons-email + 1.2 + + + + + org.codehaus.sonar + sonar-testing-harness + test + + + dumbster + dumbster + 1.6 + test + + + + + + + org.codehaus.sonar + sonar-packaging-maven-plugin + true + + Email notifications + org.sonar.plugins.emailnotifications.EmailNotificationsPlugin + + + + + diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailConfiguration.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailConfiguration.java new file mode 100644 index 00000000000..907d9bf599c --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailConfiguration.java @@ -0,0 +1,86 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications; + +import org.apache.commons.configuration.Configuration; +import org.sonar.api.CoreProperties; +import org.sonar.api.ServerExtension; + +/** + * Ruby uses constants from this class. + * + * @since 2.10 + */ +public class EmailConfiguration implements ServerExtension { + + public static final String SMTP_HOST = "email.smtp_host.secured"; + public static final String SMTP_HOST_DEFAULT = ""; + public static final String SMTP_PORT = "email.smtp_port.secured"; + public static final String SMTP_PORT_DEFAULT = "25"; + public static final String SMTP_USE_TLS = "email.smtp_use_tls.secured"; + public static final boolean SMTP_USE_TLS_DEFAULT = false; + public static final String SMTP_USERNAME = "email.smtp_username.secured"; + public static final String SMTP_USERNAME_DEFAULT = ""; + public static final String SMTP_PASSWORD = "email.smtp_password.secured"; + public static final String SMTP_PASSWORD_DEFAULT = ""; + public static final String FROM = "email.from"; + public static final String FROM_DEFAULT = "noreply@nowhere"; + public static final String PREFIX = "email.prefix"; + public static final String PREFIX_DEFAULT = "[SONAR]"; + + private Configuration configuration; + + public EmailConfiguration(Configuration configuration) { + this.configuration = configuration; + } + + public String getSmtpHost() { + return configuration.getString(SMTP_HOST, SMTP_HOST_DEFAULT); + } + + public String getSmtpPort() { + return configuration.getString(SMTP_PORT, SMTP_PORT_DEFAULT); + } + + public boolean isUseTLS() { + return configuration.getBoolean(SMTP_USE_TLS, SMTP_USE_TLS_DEFAULT); + } + + public String getSmtpUsername() { + return configuration.getString(SMTP_USERNAME, SMTP_USERNAME_DEFAULT); + } + + public String getSmtpPassword() { + return configuration.getString(SMTP_PASSWORD, SMTP_PASSWORD_DEFAULT); + } + + public String getFrom() { + return configuration.getString(FROM, FROM_DEFAULT); + } + + public String getPrefix() { + return configuration.getString(PREFIX, PREFIX_DEFAULT); + } + + public String getServerBaseURL() { + return configuration.getString(CoreProperties.SERVER_BASE_URL, CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationChannel.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationChannel.java new file mode 100644 index 00000000000..74fb59d5d0e --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationChannel.java @@ -0,0 +1,190 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.mail.EmailException; +import org.apache.commons.mail.SimpleEmail; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.database.model.User; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationChannel; +import org.sonar.api.security.UserFinder; +import org.sonar.plugins.emailnotifications.api.EmailMessage; +import org.sonar.plugins.emailnotifications.api.EmailTemplate; + +/** + * References: + * + * + * @since 2.10 + */ +public class EmailNotificationChannel extends NotificationChannel { + + private static final Logger LOG = LoggerFactory.getLogger(EmailNotificationChannel.class); + + /** + * @see org.apache.commons.mail.Email#setSocketConnectionTimeout(int) + * @see org.apache.commons.mail.Email#setSocketTimeout(int) + */ + private static final int SOCKET_TIMEOUT = 30000; + + /** + * Email Header Field: "List-ID". + * Value of this field should contain mailing list identifier as specified in RFC 2919. + */ + private static final String LIST_ID_HEADER = "List-ID"; + + /** + * Email Header Field: "List-Archive". + * Value of this field should contain URL of mailing list archive as specified in RFC 2369. + */ + private static final String LIST_ARCHIVE_HEADER = "List-Archive"; + + /** + * Email Header Field: "In-Reply-To". + * Value of this field should contain related message identifier as specified in RFC 2822. + */ + private static final String IN_REPLY_TO_HEADER = "In-Reply-To"; + + /** + * Email Header Field: "References". + * Value of this field should contain related message identifier as specified in RFC 2822 + */ + private static final String REFERENCES_HEADER = "References"; + + private static final String FROM_NAME_DEFAULT = "Sonar"; + private static final String SUBJECT_DEFAULT = "Notification"; + + private EmailConfiguration configuration; + private EmailTemplate[] templates; + private UserFinder userFinder; + + public EmailNotificationChannel(EmailConfiguration configuration, EmailTemplate[] templates, UserFinder userFinder) { + this.configuration = configuration; + this.templates = templates; + this.userFinder = userFinder; + } + + @Override + public void deliver(Notification notification, String username) { + User user = userFinder.findByLogin(username); + if (StringUtils.isBlank(user.getEmail())) { + LOG.warn("Email not defined for user: " + username); + return; + } + EmailMessage emailMessage = format(notification); + if (emailMessage != null) { + emailMessage.setTo(user.getEmail()); + deliver(emailMessage); + } + } + + private EmailMessage format(Notification notification) { + for (EmailTemplate template : templates) { + EmailMessage email = template.format(notification); + if (email != null) { + return email; + } + } + LOG.warn("Email template not found for notification: {}", notification); + return null; + } + + /** + * Visibility has been relaxed for tests. + */ + void deliver(EmailMessage emailMessage) { + if (StringUtils.isBlank(configuration.getSmtpHost())) { + LOG.warn("SMTP host was not configured - email will not be sent"); + return; + } + try { + send(emailMessage); + } catch (EmailException e) { + LOG.error("Unable to send email", e); + } + } + + private void send(EmailMessage emailMessage) throws EmailException { + LOG.info("Sending email: {}", emailMessage); + String host = null; + try { + host = new URL(configuration.getServerBaseURL()).getHost(); + } catch (MalformedURLException e) { + // ignore + } + + SimpleEmail email = new SimpleEmail(); + if (StringUtils.isNotBlank(host)) { + /* + * Set headers for proper threading: GMail will not group messages, even if they have same subject, but don't have "In-Reply-To" and + * "References" headers. TODO investigate threading in other clients like KMail, Thunderbird, Outlook + */ + if (StringUtils.isNotEmpty(emailMessage.getMessageId())) { + String messageId = "<" + emailMessage.getMessageId() + "@" + host + ">"; + email.addHeader(IN_REPLY_TO_HEADER, messageId); + email.addHeader(REFERENCES_HEADER, messageId); + } + // Set headers for proper filtering + email.addHeader(LIST_ID_HEADER, "Sonar "); + email.addHeader(LIST_ARCHIVE_HEADER, configuration.getServerBaseURL()); + } + // Set general information + email.setFrom(configuration.getFrom(), StringUtils.defaultIfBlank(emailMessage.getFrom(), FROM_NAME_DEFAULT)); + email.addTo(emailMessage.getTo(), " "); + String subject = StringUtils.defaultIfBlank(StringUtils.trimToEmpty(configuration.getPrefix()) + " ", "") + + StringUtils.defaultString(emailMessage.getSubject(), SUBJECT_DEFAULT); + email.setSubject(subject); + email.setMsg(emailMessage.getMessage()); + // Send + email.setHostName(configuration.getSmtpHost()); + email.setSmtpPort(Integer.parseInt(configuration.getSmtpPort())); + email.setTLS(configuration.isUseTLS()); + if (StringUtils.isNotBlank(configuration.getSmtpUsername()) || StringUtils.isNotBlank(configuration.getSmtpPassword())) { + email.setAuthentication(configuration.getSmtpUsername(), configuration.getSmtpPassword()); + } + email.setSocketConnectionTimeout(SOCKET_TIMEOUT); + email.setSocketTimeout(SOCKET_TIMEOUT); + email.send(); + } + + /** + * Send test email. This method called from Ruby. + * + * @throws EmailException when unable to send + */ + public void sendTestEmail(String toAddress, String subject, String message) throws EmailException { + EmailMessage emailMessage = new EmailMessage(); + emailMessage.setTo(toAddress); + emailMessage.setSubject(subject); + emailMessage.setMessage(message); + send(emailMessage); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java new file mode 100644 index 00000000000..c5cc4ccc7de --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java @@ -0,0 +1,42 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications; + +import org.sonar.api.SonarPlugin; +import org.sonar.plugins.emailnotifications.reviews.ChangesInReviewAssignedToMe; +import org.sonar.plugins.emailnotifications.reviews.ChangesInReviewCreatedByMe; +import org.sonar.plugins.emailnotifications.reviews.ReviewEmailTemplate; + +import java.util.Arrays; +import java.util.List; + +public class EmailNotificationsPlugin extends SonarPlugin { + + public List getExtensions() { + return Arrays.asList( + EmailConfiguration.class, + EmailNotificationChannel.class, + + ReviewEmailTemplate.class, + ChangesInReviewAssignedToMe.class, + ChangesInReviewCreatedByMe.class); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/api/EmailMessage.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/api/EmailMessage.java new file mode 100644 index 00000000000..f03d90caea6 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/api/EmailMessage.java @@ -0,0 +1,115 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.api; + +import org.apache.commons.lang.builder.ToStringBuilder; + +/** + * @since 2.10 + */ +public class EmailMessage { + + private String from; + private String to; + private String subject; + private String message; + private String messageId; + + /** + * @param from full name of user, who initiated this message or null, if message was initiated by Sonar + */ + public EmailMessage setFrom(String from) { + this.from = from; + return this; + } + + /** + * @see #setFrom(String) + */ + public String getFrom() { + return from; + } + + /** + * @param to email address where to send this message + */ + public EmailMessage setTo(String to) { + this.to = to; + return this; + } + + /** + * @see #setTo(String) + */ + public String getTo() { + return to; + } + + /** + * @param subject message subject + */ + public EmailMessage setSubject(String subject) { + this.subject = subject; + return this; + } + + /** + * @see #setSubject(String) + */ + public String getSubject() { + return subject; + } + + /** + * @param message message body + */ + public EmailMessage setMessage(String message) { + this.message = message; + return this; + } + + /** + * @see #setMessage(String) + */ + public String getMessage() { + return message; + } + + /** + * @param messageId id of message for threading + */ + public EmailMessage setMessageId(String messageId) { + this.messageId = messageId; + return this; + } + + /** + * @see #setMessageId(String) + */ + public String getMessageId() { + return messageId; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/api/EmailTemplate.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/api/EmailTemplate.java new file mode 100644 index 00000000000..fe638eada73 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/api/EmailTemplate.java @@ -0,0 +1,32 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.api; + +import org.sonar.api.ServerExtension; +import org.sonar.api.notifications.Notification; + +/** + * @since 2.10 + */ +public abstract class EmailTemplate implements ServerExtension { + + public abstract EmailMessage format(Notification notification); + +} diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewAssignedToMe.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewAssignedToMe.java new file mode 100644 index 00000000000..c5859ee13da --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewAssignedToMe.java @@ -0,0 +1,48 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.reviews; + +import org.apache.commons.lang.StringUtils; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationDispatcher; + +/** + * This dispatcher means: "notify me when when someone changes review assigned to me". + * + * @since 2.10 + */ +public class ChangesInReviewAssignedToMe extends NotificationDispatcher { + + @Override + public void dispatch(Notification notification, Context context) { + if (StringUtils.startsWith(notification.getType(), "review")) { + String author = notification.getFieldValue("author"); // author of change + String oldAssignee = notification.getFieldValue("old.assignee"); // previous assignee + String assignee = notification.getFieldValue("assignee"); // current assignee + if (!StringUtils.equals(author, oldAssignee)) { + context.addUser(oldAssignee); + } + if (!StringUtils.equals(author, assignee)) { + context.addUser(assignee); + } + } + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewCreatedByMe.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewCreatedByMe.java new file mode 100644 index 00000000000..85f104637d0 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewCreatedByMe.java @@ -0,0 +1,44 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.reviews; + +import org.apache.commons.lang.StringUtils; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationDispatcher; + +/** + * This dispatcher means: "notify me when when someone changes review created by me". + * + * @since 2.10 + */ +public class ChangesInReviewCreatedByMe extends NotificationDispatcher { + + @Override + public void dispatch(Notification notification, Context context) { + if (StringUtils.startsWith(notification.getType(), "review")) { + String author = notification.getFieldValue("author"); // author of change + String creator = notification.getFieldValue("creator"); // creator of review + if (!StringUtils.equals(author, creator)) { + context.addUser(creator); + } + } + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ReviewEmailTemplate.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ReviewEmailTemplate.java new file mode 100644 index 00000000000..f09082a2d07 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/reviews/ReviewEmailTemplate.java @@ -0,0 +1,117 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.reviews; + +import org.apache.commons.lang.StringUtils; +import org.sonar.api.database.model.User; +import org.sonar.api.notifications.Notification; +import org.sonar.api.security.UserFinder; +import org.sonar.plugins.emailnotifications.EmailConfiguration; +import org.sonar.plugins.emailnotifications.api.EmailMessage; +import org.sonar.plugins.emailnotifications.api.EmailTemplate; + +/** + * Creates email message for notification "review-changed". + * + * @since 2.10 + */ +public class ReviewEmailTemplate extends EmailTemplate { + + private EmailConfiguration configuration; + private UserFinder userFinder; + + public ReviewEmailTemplate(EmailConfiguration configuration, UserFinder userFinder) { + this.configuration = configuration; + this.userFinder = userFinder; + } + + @Override + public EmailMessage format(Notification notification) { + if ( !"review-changed".equals(notification.getType())) { + return null; + } + String reviewId = notification.getFieldValue("reviewId"); + String author = notification.getFieldValue("author"); + StringBuilder sb = new StringBuilder(); + + append(sb, "Status", notification.getFieldValue("old.status"), notification.getFieldValue("new.status")); + append(sb, "Resolution", notification.getFieldValue("old.resolution"), notification.getFieldValue("new.resolution")); + append(sb, "Assignee", getUserFullName(notification.getFieldValue("old.assignee")), getUserFullName(notification.getFieldValue("new.assignee"))); + appendComment(sb, notification); + appendFooter(sb, notification); + + EmailMessage message = new EmailMessage() + .setMessageId("review/" + reviewId) + .setSubject("Review #" + reviewId) + .setMessage(sb.toString()); + if (author != null) { + message.setFrom(getUserFullName(author)); + } + return message; + } + + private void append(StringBuilder sb, String name, String oldValue, String newValue) { + if (oldValue != null || newValue != null) { + sb.append(name).append(": "); + if (newValue != null) { + sb.append(newValue); + } + if (oldValue != null) { + sb.append(" (was ").append(oldValue).append(")"); + } + sb.append('\n'); + } + } + + private void appendComment(StringBuilder sb, Notification notification) { + String newComment = notification.getFieldValue("new.comment"); + String oldComment = notification.getFieldValue("old.comment"); + + if (newComment != null) { // comment was added or modified + sb.append("Comment:\n ").append(newComment).append('\n'); + if (oldComment != null) { // comment was modified + sb.append("Was:\n ").append(oldComment).append('\n'); + } + } else if (oldComment != null) { // comment was deleted + sb.append("Comment deleted, was:\n ").append(oldComment).append('\n'); + } + } + + private void appendFooter(StringBuilder sb, Notification notification) { + String reviewId = notification.getFieldValue("reviewId"); + sb.append("\n--\n") + .append("See it in Sonar: ").append(configuration.getServerBaseURL()).append("/review/view/").append(reviewId).append('\n'); + } + + /** + * Visibility has been relaxed for tests. + */ + String getUserFullName(String login) { + if (login == null) { + return null; + } + User user = userFinder.findByLogin(login); + if (user == null) { // most probably user was deleted + return login; + } + return StringUtils.defaultIfBlank(user.getName(), login); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailConfigurationTest.java b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailConfigurationTest.java new file mode 100644 index 00000000000..92c3ab5c1df --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailConfigurationTest.java @@ -0,0 +1,53 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import org.apache.commons.configuration.BaseConfiguration; +import org.apache.commons.configuration.Configuration; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.CoreProperties; + +public class EmailConfigurationTest { + + private EmailConfiguration emailConfiguration; + + @Before + public void setUp() { + Configuration configuration = new BaseConfiguration(); + emailConfiguration = new EmailConfiguration(configuration); + } + + @Test + public void shouldReturnDefaultValues() { + assertThat(emailConfiguration.getSmtpHost(), is("")); + assertThat(emailConfiguration.getSmtpPort(), is("25")); + assertThat(emailConfiguration.getSmtpUsername(), is("")); + assertThat(emailConfiguration.getSmtpPassword(), is("")); + assertThat(emailConfiguration.isUseTLS(), is(false)); + assertThat(emailConfiguration.getFrom(), is("noreply@nowhere")); + assertThat(emailConfiguration.getPrefix(), is("[SONAR]")); + assertThat(emailConfiguration.getServerBaseURL(), is(CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE)); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationChannelTest.java b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationChannelTest.java new file mode 100644 index 00000000000..18c1e238de5 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationChannelTest.java @@ -0,0 +1,182 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.net.ServerSocket; + +import org.apache.commons.mail.EmailException; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.sonar.plugins.emailnotifications.api.EmailMessage; + +import com.dumbster.smtp.SimpleSmtpServer; +import com.dumbster.smtp.SmtpMessage; + +public class EmailNotificationChannelTest { + + private static int port; + + private SimpleSmtpServer server; + + private EmailConfiguration configuration; + private EmailNotificationChannel channel; + + @BeforeClass + public static void selectPort() { + port = getNextAvailablePort(); + } + + private static int getNextAvailablePort() { + try { + ServerSocket socket = new ServerSocket(0); + int unusedPort = socket.getLocalPort(); + socket.close(); + return unusedPort; + } catch (IOException e) { + throw new RuntimeException("Error getting an available port from system", e); + } + } + + @Before + public void setUp() { + server = SimpleSmtpServer.start(port); + configuration = mock(EmailConfiguration.class); + channel = new EmailNotificationChannel(configuration, null, null); + } + + @After + public void tearDown() { + if (!server.isStopped()) { + server.stop(); + } + } + + @Test + public void shouldSendTestEmail() throws Exception { + configure(); + channel.sendTestEmail("user@nowhere", "Test Message from Sonar", "This is a test message from Sonar."); + + assertThat(server.getReceivedEmailSize(), is(1)); + SmtpMessage email = (SmtpMessage) server.getReceivedEmail().next(); + + assertThat(email.getHeaderValue("From"), is("Sonar ")); + assertThat(email.getHeaderValue("To"), is("")); + assertThat(email.getHeaderValue("Subject"), is("[SONAR] Test Message from Sonar")); + assertThat(email.getBody(), is("This is a test message from Sonar.")); + } + + @Test(expected = EmailException.class) + public void shouldThrowAnExceptionWhenUnableToSendTestEmail() throws Exception { + configure(); + server.stop(); + + channel.sendTestEmail("user@nowhere", "Test Message from Sonar", "This is a test message from Sonar."); + } + + @Test + public void shouldNotSendEmailWhenHostnameNotConfigured() throws Exception { + EmailMessage emailMessage = new EmailMessage() + .setTo("user@nowhere") + .setSubject("Foo") + .setMessage("Bar"); + channel.deliver(emailMessage); + assertThat(server.getReceivedEmailSize(), is(0)); + } + + @Test + public void shouldSendThreadedEmail() throws Exception { + configure(); + EmailMessage emailMessage = new EmailMessage() + .setMessageId("reviews/view/1") + .setFrom("Full Username") + .setTo("user@nowhere") + .setSubject("Review #3") + .setMessage("I'll take care of this violation."); + channel.deliver(emailMessage); + + assertThat(server.getReceivedEmailSize(), is(1)); + SmtpMessage email = (SmtpMessage) server.getReceivedEmail().next(); + + assertThat(email.getHeaderValue("In-Reply-To"), is("")); + assertThat(email.getHeaderValue("References"), is("")); + + assertThat(email.getHeaderValue("List-ID"), is("Sonar ")); + assertThat(email.getHeaderValue("List-Archive"), is("http://nemo.sonarsource.org")); + + assertThat(email.getHeaderValue("From"), is("Full Username ")); + assertThat(email.getHeaderValue("To"), is("")); + assertThat(email.getHeaderValue("Subject"), is("[SONAR] Review #3")); + assertThat(email.getBody(), is("I'll take care of this violation.")); + } + + @Test + public void shouldSendNonThreadedEmail() throws Exception { + configure(); + EmailMessage emailMessage = new EmailMessage() + .setTo("user@nowhere") + .setSubject("Foo") + .setMessage("Bar"); + channel.deliver(emailMessage); + + assertThat(server.getReceivedEmailSize(), is(1)); + SmtpMessage email = (SmtpMessage) server.getReceivedEmail().next(); + + assertThat(email.getHeaderValue("In-Reply-To"), nullValue()); + assertThat(email.getHeaderValue("References"), nullValue()); + + assertThat(email.getHeaderValue("List-ID"), is("Sonar ")); + assertThat(email.getHeaderValue("List-Archive"), is("http://nemo.sonarsource.org")); + + assertThat(email.getHeaderValue("From"), is("Sonar ")); + assertThat(email.getHeaderValue("To"), is("")); + assertThat(email.getHeaderValue("Subject"), is("[SONAR] Foo")); + assertThat(email.getBody(), is("Bar")); + } + + @Test + public void shouldNotThrowAnExceptionWhenUnableToSendEmail() throws Exception { + configure(); + server.stop(); + + EmailMessage emailMessage = new EmailMessage() + .setTo("user@nowhere") + .setSubject("Foo") + .setMessage("Bar"); + channel.deliver(emailMessage); + } + + private void configure() { + when(configuration.getSmtpHost()).thenReturn("localhost"); + when(configuration.getSmtpPort()).thenReturn(Integer.toString(port)); + when(configuration.getFrom()).thenReturn("server@nowhere"); + when(configuration.getPrefix()).thenReturn("[SONAR]"); + when(configuration.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org"); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationsPluginTest.java b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationsPluginTest.java new file mode 100644 index 00000000000..b6deef32eb8 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationsPluginTest.java @@ -0,0 +1,34 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications; + +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.Assert.assertThat; + +import org.junit.Test; + +public class EmailNotificationsPluginTest { + + @Test + public void testGetExtensions() { + assertThat(new EmailNotificationsPlugin().getExtensions().size(), greaterThan(1)); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewAssignedToMeTest.java b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewAssignedToMeTest.java new file mode 100644 index 00000000000..e9b169c6363 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewAssignedToMeTest.java @@ -0,0 +1,78 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.reviews; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationDispatcher; + +public class ChangesInReviewAssignedToMeTest { + + private NotificationDispatcher.Context context; + private ChangesInReviewAssignedToMe dispatcher; + + @Before + public void setUp() { + context = mock(NotificationDispatcher.Context.class); + dispatcher = new ChangesInReviewAssignedToMe(); + } + + @Test + public void dispatchToOldAndNewAssignee() { + Notification notification = new Notification("review-assignee-changed") + .setFieldValue("author", "freddy") + .setFieldValue("old.assignee", "godin") + .setFieldValue("assignee", "simon"); + + dispatcher.dispatch(notification, context); + + verify(context).addUser("godin"); + verify(context).addUser("simon"); + verifyNoMoreInteractions(context); + } + + @Test + public void doNotDispatchToAuthorOfChanges() { + Notification notification = new Notification("review-assignee-changed") + .setFieldValue("author", "simon") + .setFieldValue("old.assignee", "simon") + .setFieldValue("assignee", "godin"); + + dispatcher.dispatch(notification, context); + + verify(context).addUser("godin"); + verifyNoMoreInteractions(context); + } + + @Test + public void shouldNotDispatch() { + Notification notification = new Notification("other"); + + dispatcher.dispatch(notification, context); + + verifyNoMoreInteractions(context); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewCreatedByMeTest.java b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewCreatedByMeTest.java new file mode 100644 index 00000000000..3f3142ccced --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ChangesInReviewCreatedByMeTest.java @@ -0,0 +1,74 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.reviews; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationDispatcher; + +public class ChangesInReviewCreatedByMeTest { + + private NotificationDispatcher.Context context; + private ChangesInReviewCreatedByMe dispatcher; + + @Before + public void setUp() { + context = mock(NotificationDispatcher.Context.class); + dispatcher = new ChangesInReviewCreatedByMe(); + } + + @Test + public void dispatchToCreator() { + Notification notification = new Notification("review-comment-added") + .setFieldValue("author", "godin") + .setFieldValue("creator", "simon"); + + dispatcher.dispatch(notification, context); + + verify(context).addUser("simon"); + verifyNoMoreInteractions(context); + } + + @Test + public void doNotDispatchToAuthorOfChanges() { + Notification notification = new Notification("review-comment-added") + .setFieldValue("author", "simon") + .setFieldValue("creator", "simon"); + + dispatcher.dispatch(notification, context); + + verifyNoMoreInteractions(context); + } + + @Test + public void shouldNotDispatch() { + Notification notification = new Notification("other"); + + dispatcher.dispatch(notification, context); + + verifyNoMoreInteractions(context); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ReviewEmailTemplateTest.java b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ReviewEmailTemplateTest.java new file mode 100644 index 00000000000..70fca60f6b8 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/reviews/ReviewEmailTemplateTest.java @@ -0,0 +1,330 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.reviews; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.database.model.User; +import org.sonar.api.notifications.Notification; +import org.sonar.api.security.UserFinder; +import org.sonar.plugins.emailnotifications.EmailConfiguration; +import org.sonar.plugins.emailnotifications.api.EmailMessage; + +public class ReviewEmailTemplateTest { + + private ReviewEmailTemplate template; + + @Before + public void setUp() { + EmailConfiguration configuration = mock(EmailConfiguration.class); + when(configuration.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org"); + UserFinder userFinder = mock(UserFinder.class); + when(userFinder.findByLogin(eq("freddy.mallet"))).thenReturn(new User().setName("Freddy Mallet")); + when(userFinder.findByLogin(eq("simon.brandhof"))).thenReturn(new User().setName("Simon Brandhof")); + when(userFinder.findByLogin(eq("evgeny.mandrikov"))).thenReturn(new User().setName("Evgeny Mandrikov")); + template = new ReviewEmailTemplate(configuration, userFinder); + } + + /** + *
+   * Subject: Review #1
+   * From: Freddy Mallet
+   * 
+   * Comment:
+   *   This is my first comment
+   * 
+   * --
+   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
+   * 
+ */ + @Test + public void shouldFormatCommentAdded() { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", "1") + .setFieldValue("author", "freddy.mallet") + .setFieldValue("old.comment", null) + .setFieldValue("new.comment", "This is my first comment"); + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("review/1")); + assertThat(message.getSubject(), is("Review #1")); + assertThat(message.getFrom(), is("Freddy Mallet")); + assertThat(message.getMessage(), is("Comment:\n This is my first comment\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); + } + + /** + *
+   * Subject: Review #1
+   * From: Freddy Mallet
+   * 
+   * Comment:
+   *   This is another comment
+   * Was:
+   *   This is my first comment
+   * 
+   * --
+   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
+   * 
+ */ + @Test + public void shouldFormatCommentEdited() { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", "1") + .setFieldValue("author", "freddy.mallet") + .setFieldValue("old.comment", "This is my first comment") + .setFieldValue("new.comment", "This is another comment"); + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("review/1")); + assertThat(message.getSubject(), is("Review #1")); + assertThat(message.getFrom(), is("Freddy Mallet")); + assertThat(message.getMessage(), is("Comment:\n This is another comment\nWas:\n This is my first comment\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); + } + + /** + *
+   * Subject: Review #1
+   * From: Freddy Mallet
+   * 
+   * Comment deleted, was:
+   *   This is deleted comment
+   *   
+   * --
+   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
+   * 
+ */ + @Test + public void shouldFormatCommentDeleted() { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", "1") + .setFieldValue("old.comment", "This is deleted comment") + .setFieldValue("new.comment", null) + .setFieldValue("author", "freddy.mallet"); + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("review/1")); + assertThat(message.getSubject(), is("Review #1")); + assertThat(message.getFrom(), is("Freddy Mallet")); + assertThat(message.getMessage(), is("Comment deleted, was:\n This is deleted comment\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); + } + + /** + *
+   * Subject: Review #1
+   * From: Freddy Mallet
+   * 
+   * Assignee: Evgeny Mandrikov
+   * 
+   * --
+   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
+   * 
+ */ + @Test + public void shouldFormatAssigneed() { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", "1") + .setFieldValue("author", "freddy.mallet") + .setFieldValue("old.assignee", null) + .setFieldValue("new.assignee", "evgeny.mandrikov"); + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("review/1")); + assertThat(message.getSubject(), is("Review #1")); + assertThat(message.getFrom(), is("Freddy Mallet")); + assertThat(message.getMessage(), is("Assignee: Evgeny Mandrikov\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); + } + + /** + *
+   * Subject: Review #1
+   * From: Freddy Mallet
+   * 
+   * Assignee: Simon Brandhof (was Evgeny Mandrikov)
+   * 
+   * --
+   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
+   * 
+ */ + @Test + public void shouldFormatAssigneedToAnotherPerson() { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", "1") + .setFieldValue("author", "freddy.mallet") + .setFieldValue("old.assignee", "evgeny.mandrikov") + .setFieldValue("new.assignee", "simon.brandhof"); + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("review/1")); + assertThat(message.getSubject(), is("Review #1")); + assertThat(message.getFrom(), is("Freddy Mallet")); + assertThat(message.getMessage(), is("Assignee: Simon Brandhof (was Evgeny Mandrikov)\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); + } + + /** + *
+   * Subject: Review #1
+   * From: Freddy Mallet
+   * 
+   * Assignee: (was Simon Brandhof)
+   * 
+   * --
+   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
+   * 
+ */ + @Test + public void shouldFormatUnassigned() { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", "1") + .setFieldValue("author", "freddy.mallet") + .setFieldValue("old.assignee", "simon.brandhof") + .setFieldValue("new.assignee", null); + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("review/1")); + assertThat(message.getSubject(), is("Review #1")); + assertThat(message.getFrom(), is("Freddy Mallet")); + assertThat(message.getMessage(), is("Assignee: (was Simon Brandhof)\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); + } + + /** + *
+   * Subject: Review #1
+   * From: Sonar
+   * 
+   * Status: CLOSED (was OPEN)
+   * 
+   * --
+   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
+   * 
+ */ + @Test + public void shouldFormatClosed() { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", "1") + .setFieldValue("old.status", "OPEN") + .setFieldValue("new.status", "CLOSED"); + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("review/1")); + assertThat(message.getSubject(), is("Review #1")); + assertThat(message.getFrom(), nullValue()); + assertThat(message.getMessage(), is("Status: CLOSED (was OPEN)\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); + } + + /** + *
+   * Subject: Review #1
+   * From: Simon Brandhof
+   * 
+   * Status: REOPENED (was RESOLVED)
+   * Resolution: (was FIXED)
+   * 
+   * --
+   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
+   * 
+ */ + @Test + public void shouldFormatReopened() { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", "1") + .setFieldValue("old.resolution", "FIXED") + .setFieldValue("new.resolution", null) + .setFieldValue("old.status", "RESOLVED") + .setFieldValue("new.status", "REOPENED"); + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("review/1")); + assertThat(message.getSubject(), is("Review #1")); + assertThat(message.getFrom(), nullValue()); + assertThat(message.getMessage(), is("Status: REOPENED (was RESOLVED)\nResolution: (was FIXED)\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); + } + + /** + *
+   * Subject: Review #1
+   * From: Simon Brandhof
+   * 
+   * Status: RESOLVED (was OPEN)
+   * Resolution: FIXED
+   * 
+   * --
+   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
+   * 
+ */ + @Test + public void shouldFormatResolvedAsFixed() { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", "1") + .setFieldValue("author", "simon.brandhof") + .setFieldValue("old.status", "OPEN") + .setFieldValue("old.resolution", null) + .setFieldValue("new.status", "RESOLVED") + .setFieldValue("new.resolution", "FIXED"); + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("review/1")); + assertThat(message.getSubject(), is("Review #1")); + assertThat(message.getFrom(), is("Simon Brandhof")); + assertThat(message.getMessage(), is("Status: RESOLVED (was OPEN)\nResolution: FIXED\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); + } + + /** + *
+   * Subject: Review #1
+   * From: Simon Brandhof
+   * 
+   * Status: RESOLVED (was REOPENED)
+   * Resolution: FALSE-POSITIVE
+   * Comment:
+   *   Because!
+   * 
+   * --
+   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
+   * 
+ */ + @Test + public void shouldFormatResolvedAsFalsePositive() { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", "1") + .setFieldValue("author", "freddy.mallet") + .setFieldValue("old.status", "REOPENED") + .setFieldValue("old.resolution", null) + .setFieldValue("new.status", "RESOLVED") + .setFieldValue("new.resolution", "FALSE-POSITIVE") + .setFieldValue("new.comment", "Because!"); + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("review/1")); + assertThat(message.getSubject(), is("Review #1")); + assertThat(message.getFrom(), is("Freddy Mallet")); + assertThat(message.getMessage(), is("Status: RESOLVED (was REOPENED)\nResolution: FALSE-POSITIVE\nComment:\n Because!\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); + } + + @Test + public void shouldNotFormat() { + Notification notification = new Notification("other"); + EmailMessage message = template.format(notification); + assertThat(message, nullValue()); + } + + @Test + public void shouldReturnFullNameOrLogin() { + assertThat(template.getUserFullName("freddy.mallet"), is("Freddy Mallet")); + assertThat(template.getUserFullName("deleted"), is("deleted")); + } + +} diff --git a/plugins/sonar-email-plugin/pom.xml b/plugins/sonar-email-plugin/pom.xml deleted file mode 100644 index 7a6fc713694..00000000000 --- a/plugins/sonar-email-plugin/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - 4.0.0 - - - org.codehaus.sonar - sonar - 2.10-SNAPSHOT - ../.. - - - org.codehaus.sonar.plugins - sonar-email-plugin - sonar-plugin - - Sonar :: Plugins :: Email - - - - org.codehaus.sonar - sonar-plugin-api - provided - - - org.codehaus.sonar - sonar-core - provided - - - org.apache.commons - commons-email - 1.2 - - - - - org.codehaus.sonar - sonar-testing-harness - test - - - dumbster - dumbster - 1.6 - test - - - - - - - org.codehaus.sonar - sonar-packaging-maven-plugin - true - - Email - org.sonar.plugins.email.EmailPlugin - - - - - - diff --git a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailConfiguration.java b/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailConfiguration.java deleted file mode 100644 index 63b5f43cf19..00000000000 --- a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailConfiguration.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email; - -import org.apache.commons.configuration.Configuration; -import org.sonar.api.CoreProperties; -import org.sonar.api.ServerExtension; - -/** - * Ruby uses constants from this class. - * - * @since 2.10 - */ -public class EmailConfiguration implements ServerExtension { - - public static final String SMTP_HOST = "email.smtp_host"; - public static final String SMTP_HOST_DEFAULT = ""; - public static final String SMTP_PORT = "email.smtp_port"; - public static final String SMTP_PORT_DEFAULT = "25"; - public static final String SMTP_USE_TLS = "email.smtp_use_tls"; - public static final boolean SMTP_USE_TLS_DEFAULT = false; - public static final String SMTP_USERNAME = "email.smtp_username"; - public static final String SMTP_USERNAME_DEFAULT = ""; - public static final String SMTP_PASSWORD = "email.smtp_password"; - public static final String SMTP_PASSWORD_DEFAULT = ""; - public static final String FROM = "email.from"; - public static final String FROM_DEFAULT = "noreply@nowhere"; - public static final String PREFIX = "email.prefix"; - public static final String PREFIX_DEFAULT = "[SONAR]"; - - private Configuration configuration; - - public EmailConfiguration(Configuration configuration) { - this.configuration = configuration; - } - - public String getSmtpHost() { - return configuration.getString(SMTP_HOST, SMTP_HOST_DEFAULT); - } - - public String getSmtpPort() { - return configuration.getString(SMTP_PORT, SMTP_PORT_DEFAULT); - } - - public boolean isUseTLS() { - return configuration.getBoolean(SMTP_USE_TLS, SMTP_USE_TLS_DEFAULT); - } - - public String getSmtpUsername() { - return configuration.getString(SMTP_USERNAME, SMTP_USERNAME_DEFAULT); - } - - public String getSmtpPassword() { - return configuration.getString(SMTP_PASSWORD, SMTP_PASSWORD_DEFAULT); - } - - public String getFrom() { - return configuration.getString(FROM, FROM_DEFAULT); - } - - public String getPrefix() { - return configuration.getString(PREFIX, PREFIX_DEFAULT); - } - - public String getServerBaseURL() { - return configuration.getString(CoreProperties.SERVER_BASE_URL, CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE); - } - -} diff --git a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailNotificationChannel.java b/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailNotificationChannel.java deleted file mode 100644 index b35aecd623f..00000000000 --- a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailNotificationChannel.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email; - -import java.net.MalformedURLException; -import java.net.URL; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.mail.EmailException; -import org.apache.commons.mail.SimpleEmail; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.database.model.User; -import org.sonar.api.notifications.Notification; -import org.sonar.api.notifications.NotificationChannel; -import org.sonar.api.security.UserFinder; -import org.sonar.plugins.email.api.EmailMessage; -import org.sonar.plugins.email.api.EmailTemplate; - -/** - * References: - * - * - * @since 2.10 - */ -public class EmailNotificationChannel extends NotificationChannel { - - private static final Logger LOG = LoggerFactory.getLogger(EmailNotificationChannel.class); - - /** - * @see org.apache.commons.mail.Email#setSocketConnectionTimeout(int) - * @see org.apache.commons.mail.Email#setSocketTimeout(int) - */ - private static final int SOCKET_TIMEOUT = 30000; - - /** - * Email Header Field: "List-ID". - * Value of this field should contain mailing list identifier as specified in RFC 2919. - */ - private static final String LIST_ID_HEADER = "List-ID"; - - /** - * Email Header Field: "List-Archive". - * Value of this field should contain URL of mailing list archive as specified in RFC 2369. - */ - private static final String LIST_ARCHIVE_HEADER = "List-Archive"; - - /** - * Email Header Field: "In-Reply-To". - * Value of this field should contain related message identifier as specified in RFC 2822. - */ - private static final String IN_REPLY_TO_HEADER = "In-Reply-To"; - - /** - * Email Header Field: "References". - * Value of this field should contain related message identifier as specified in RFC 2822 - */ - private static final String REFERENCES_HEADER = "References"; - - private static final String FROM_NAME_DEFAULT = "Sonar"; - private static final String SUBJECT_DEFAULT = "Notification"; - - private EmailConfiguration configuration; - private EmailTemplate[] templates; - private UserFinder userFinder; - - public EmailNotificationChannel(EmailConfiguration configuration, EmailTemplate[] templates, UserFinder userFinder) { - this.configuration = configuration; - this.templates = templates; - this.userFinder = userFinder; - } - - @Override - public void deliver(Notification notification, String username) { - User user = userFinder.findByLogin(username); - if (StringUtils.isBlank(user.getEmail())) { - LOG.warn("Email not defined for user: " + username); - return; - } - EmailMessage emailMessage = format(notification, username); - if (emailMessage != null) { - emailMessage.setTo(user.getEmail()); - deliver(emailMessage); - } - } - - private EmailMessage format(Notification notification, String username) { - for (EmailTemplate template : templates) { - EmailMessage email = template.format(notification); - if (email != null) { - return email; - } - } - LOG.warn("Email template not found for notification: {}", notification); - return null; - } - - /** - * Visibility has been relaxed for tests. - */ - void deliver(EmailMessage emailMessage) { - if (StringUtils.isBlank(configuration.getSmtpHost())) { - LOG.warn("SMTP host was not configured - email will not be sent"); - return; - } - try { - send(emailMessage); - } catch (EmailException e) { - LOG.error("Unable to send email", e); - } - } - - private void send(EmailMessage emailMessage) throws EmailException { - LOG.info("Sending email: {}", emailMessage); - String host = null; - try { - host = new URL(configuration.getServerBaseURL()).getHost(); - } catch (MalformedURLException e) { - // ignore - } - - SimpleEmail email = new SimpleEmail(); - if (StringUtils.isNotBlank(host)) { - /* - * Set headers for proper threading: GMail will not group messages, even if they have same subject, but don't have "In-Reply-To" and - * "References" headers. TODO investigate threading in other clients like KMail, Thunderbird, Outlook - */ - if (StringUtils.isNotEmpty(emailMessage.getMessageId())) { - String messageId = "<" + emailMessage.getMessageId() + "@" + host + ">"; - email.addHeader(IN_REPLY_TO_HEADER, messageId); - email.addHeader(REFERENCES_HEADER, messageId); - } - // Set headers for proper filtering - email.addHeader(LIST_ID_HEADER, "Sonar "); - email.addHeader(LIST_ARCHIVE_HEADER, configuration.getServerBaseURL()); - } - // Set general information - email.setFrom(configuration.getFrom(), StringUtils.defaultIfBlank(emailMessage.getFrom(), FROM_NAME_DEFAULT)); - email.addTo(emailMessage.getTo(), " "); - String subject = StringUtils.defaultIfBlank(StringUtils.trimToEmpty(configuration.getPrefix()) + " ", "") - + StringUtils.defaultString(emailMessage.getSubject(), SUBJECT_DEFAULT); - email.setSubject(subject); - email.setMsg(emailMessage.getMessage()); - // Send - email.setHostName(configuration.getSmtpHost()); - email.setSmtpPort(Integer.parseInt(configuration.getSmtpPort())); - email.setTLS(configuration.isUseTLS()); - if (StringUtils.isNotBlank(configuration.getSmtpUsername()) || StringUtils.isNotBlank(configuration.getSmtpPassword())) { - email.setAuthentication(configuration.getSmtpUsername(), configuration.getSmtpPassword()); - } - email.setSocketConnectionTimeout(SOCKET_TIMEOUT); - email.setSocketTimeout(SOCKET_TIMEOUT); - email.send(); - } - - /** - * Send test email. This method called from Ruby. - * - * @throws EmailException when unable to send - */ - public void sendTestEmail(String toAddress, String subject, String message) throws EmailException { - EmailMessage emailMessage = new EmailMessage(); - emailMessage.setTo(toAddress); - emailMessage.setSubject(subject); - emailMessage.setMessage(message); - send(emailMessage); - } - -} diff --git a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailPlugin.java b/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailPlugin.java deleted file mode 100644 index edee6ea8044..00000000000 --- a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/EmailPlugin.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email; - -import org.sonar.api.SonarPlugin; -import org.sonar.plugins.email.reviews.ChangesInReviewAssignedToMe; -import org.sonar.plugins.email.reviews.ChangesInReviewCreatedByMe; -import org.sonar.plugins.email.reviews.ReviewEmailTemplate; - -import java.util.Arrays; -import java.util.List; - -public class EmailPlugin extends SonarPlugin { - - public List getExtensions() { - return Arrays.asList( - EmailConfiguration.class, - EmailNotificationChannel.class, - - ReviewEmailTemplate.class, - ChangesInReviewAssignedToMe.class, - ChangesInReviewCreatedByMe.class); - } - -} diff --git a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/api/EmailMessage.java b/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/api/EmailMessage.java deleted file mode 100644 index 556c72bfd24..00000000000 --- a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/api/EmailMessage.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email.api; - -import org.apache.commons.lang.builder.ToStringBuilder; - -/** - * @since 2.10 - */ -public class EmailMessage { - - private String from; - private String to; - private String subject; - private String message; - private String messageId; - - /** - * @param from full name of user, who initiated this message or null, if message was initiated by Sonar - */ - public EmailMessage setFrom(String from) { - this.from = from; - return this; - } - - /** - * @see #setFrom(String) - */ - public String getFrom() { - return from; - } - - /** - * @param to email address where to send this message - */ - public EmailMessage setTo(String to) { - this.to = to; - return this; - } - - /** - * @see #setTo(String) - */ - public String getTo() { - return to; - } - - /** - * @param subject message subject - */ - public EmailMessage setSubject(String subject) { - this.subject = subject; - return this; - } - - /** - * @see #setSubject(String) - */ - public String getSubject() { - return subject; - } - - /** - * @param message message body - */ - public EmailMessage setMessage(String message) { - this.message = message; - return this; - } - - /** - * @see #setMessage(String) - */ - public String getMessage() { - return message; - } - - /** - * @param messageId id of message for threading - */ - public EmailMessage setMessageId(String messageId) { - this.messageId = messageId; - return this; - } - - /** - * @see #setMessageId(String) - */ - public String getMessageId() { - return messageId; - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this); - } - -} diff --git a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/api/EmailTemplate.java b/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/api/EmailTemplate.java deleted file mode 100644 index 283eaf950f7..00000000000 --- a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/api/EmailTemplate.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email.api; - -import org.sonar.api.ServerExtension; -import org.sonar.api.notifications.Notification; - -/** - * @since 2.10 - */ -public abstract class EmailTemplate implements ServerExtension { - - public abstract EmailMessage format(Notification notification); - -} diff --git a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ChangesInReviewAssignedToMe.java b/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ChangesInReviewAssignedToMe.java deleted file mode 100644 index fc56412f31b..00000000000 --- a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ChangesInReviewAssignedToMe.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email.reviews; - -import org.apache.commons.lang.StringUtils; -import org.sonar.api.notifications.Notification; -import org.sonar.api.notifications.NotificationDispatcher; - -/** - * This dispatcher means: "notify me when when someone changes review assigned to me". - * - * @since 2.10 - */ -public class ChangesInReviewAssignedToMe extends NotificationDispatcher { - - @Override - public void dispatch(Notification notification, Context context) { - if (StringUtils.startsWith(notification.getType(), "review")) { - String author = notification.getFieldValue("author"); // author of change - String oldAssignee = notification.getFieldValue("old.assignee"); // previous assignee - String assignee = notification.getFieldValue("assignee"); // current assignee - if (!StringUtils.equals(author, oldAssignee)) { - context.addUser(oldAssignee); - } - if (!StringUtils.equals(author, assignee)) { - context.addUser(assignee); - } - } - } - -} diff --git a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ChangesInReviewCreatedByMe.java b/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ChangesInReviewCreatedByMe.java deleted file mode 100644 index 30c99df3ad2..00000000000 --- a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ChangesInReviewCreatedByMe.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email.reviews; - -import org.apache.commons.lang.StringUtils; -import org.sonar.api.notifications.Notification; -import org.sonar.api.notifications.NotificationDispatcher; - -/** - * This dispatcher means: "notify me when when someone changes review created by me". - * - * @since 2.10 - */ -public class ChangesInReviewCreatedByMe extends NotificationDispatcher { - - @Override - public void dispatch(Notification notification, Context context) { - if (StringUtils.startsWith(notification.getType(), "review")) { - String author = notification.getFieldValue("author"); // author of change - String creator = notification.getFieldValue("creator"); // creator of review - if (!StringUtils.equals(author, creator)) { - context.addUser(creator); - } - } - } - -} diff --git a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ReviewEmailTemplate.java b/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ReviewEmailTemplate.java deleted file mode 100644 index 94e6786f8a4..00000000000 --- a/plugins/sonar-email-plugin/src/main/java/org/sonar/plugins/email/reviews/ReviewEmailTemplate.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email.reviews; - -import org.apache.commons.lang.StringUtils; -import org.sonar.api.database.model.User; -import org.sonar.api.notifications.Notification; -import org.sonar.api.security.UserFinder; -import org.sonar.plugins.email.EmailConfiguration; -import org.sonar.plugins.email.api.EmailMessage; -import org.sonar.plugins.email.api.EmailTemplate; - -/** - * Creates email message for notification "review-changed". - * - * @since 2.10 - */ -public class ReviewEmailTemplate extends EmailTemplate { - - private EmailConfiguration configuration; - private UserFinder userFinder; - - public ReviewEmailTemplate(EmailConfiguration configuration, UserFinder userFinder) { - this.configuration = configuration; - this.userFinder = userFinder; - } - - @Override - public EmailMessage format(Notification notification) { - if ( !"review-changed".equals(notification.getType())) { - return null; - } - String reviewId = notification.getFieldValue("reviewId"); - String author = notification.getFieldValue("author"); - StringBuilder sb = new StringBuilder(); - - append(sb, "Status", notification.getFieldValue("old.status"), notification.getFieldValue("new.status")); - append(sb, "Resolution", notification.getFieldValue("old.resolution"), notification.getFieldValue("new.resolution")); - append(sb, "Assignee", getUserFullName(notification.getFieldValue("old.assignee")), getUserFullName(notification.getFieldValue("new.assignee"))); - appendComment(sb, notification); - appendFooter(sb, notification); - - EmailMessage message = new EmailMessage() - .setMessageId("review/" + reviewId) - .setSubject("Review #" + reviewId) - .setMessage(sb.toString()); - if (author != null) { - message.setFrom(getUserFullName(author)); - } - return message; - } - - private void append(StringBuilder sb, String name, String oldValue, String newValue) { - if (oldValue != null || newValue != null) { - sb.append(name).append(": "); - if (newValue != null) { - sb.append(newValue); - } - if (oldValue != null) { - sb.append(" (was ").append(oldValue).append(")"); - } - sb.append('\n'); - } - } - - private void appendComment(StringBuilder sb, Notification notification) { - String newComment = notification.getFieldValue("new.comment"); - String oldComment = notification.getFieldValue("old.comment"); - - if (newComment != null) { // comment was added or modified - sb.append("Comment:\n ").append(newComment).append('\n'); - if (oldComment != null) { // comment was modified - sb.append("Was:\n ").append(oldComment).append('\n'); - } - } else if (oldComment != null) { // comment was deleted - sb.append("Comment deleted, was:\n ").append(oldComment).append('\n'); - } - } - - private void appendFooter(StringBuilder sb, Notification notification) { - String reviewId = notification.getFieldValue("reviewId"); - sb.append("\n--\n") - .append("See it in Sonar: ").append(configuration.getServerBaseURL()).append("/review/view/").append(reviewId).append('\n'); - } - - /** - * Visibility has been relaxed for tests. - */ - String getUserFullName(String login) { - if (login == null) { - return null; - } - User user = userFinder.findByLogin(login); - if (user == null) { // most probably user was deleted - return login; - } - return StringUtils.defaultIfBlank(user.getName(), login); - } - -} diff --git a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailConfigurationTest.java b/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailConfigurationTest.java deleted file mode 100644 index a7ff4ff1814..00000000000 --- a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailConfigurationTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -import org.apache.commons.configuration.BaseConfiguration; -import org.apache.commons.configuration.Configuration; -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.CoreProperties; - -public class EmailConfigurationTest { - - private EmailConfiguration emailConfiguration; - - @Before - public void setUp() { - Configuration configuration = new BaseConfiguration(); - emailConfiguration = new EmailConfiguration(configuration); - } - - @Test - public void shouldReturnDefaultValues() { - assertThat(emailConfiguration.getSmtpHost(), is("")); - assertThat(emailConfiguration.getSmtpPort(), is("25")); - assertThat(emailConfiguration.getSmtpUsername(), is("")); - assertThat(emailConfiguration.getSmtpPassword(), is("")); - assertThat(emailConfiguration.isUseTLS(), is(false)); - assertThat(emailConfiguration.getFrom(), is("noreply@nowhere")); - assertThat(emailConfiguration.getPrefix(), is("[SONAR]")); - assertThat(emailConfiguration.getServerBaseURL(), is(CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE)); - } - -} diff --git a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailNotificationChannelTest.java b/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailNotificationChannelTest.java deleted file mode 100644 index 1508dc676f8..00000000000 --- a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailNotificationChannelTest.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email; - -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.net.ServerSocket; - -import org.apache.commons.mail.EmailException; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.sonar.plugins.email.api.EmailMessage; - -import com.dumbster.smtp.SimpleSmtpServer; -import com.dumbster.smtp.SmtpMessage; - -public class EmailNotificationChannelTest { - - private static int port; - - private SimpleSmtpServer server; - - private EmailConfiguration configuration; - private EmailNotificationChannel channel; - - @BeforeClass - public static void selectPort() { - port = getNextAvailablePort(); - } - - private static int getNextAvailablePort() { - try { - ServerSocket socket = new ServerSocket(0); - int unusedPort = socket.getLocalPort(); - socket.close(); - return unusedPort; - } catch (IOException e) { - throw new RuntimeException("Error getting an available port from system", e); - } - } - - @Before - public void setUp() { - server = SimpleSmtpServer.start(port); - configuration = mock(EmailConfiguration.class); - channel = new EmailNotificationChannel(configuration, null, null); - } - - @After - public void tearDown() { - if (!server.isStopped()) { - server.stop(); - } - } - - @Test - public void shouldSendTestEmail() throws Exception { - configure(); - channel.sendTestEmail("user@nowhere", "Test Message from Sonar", "This is a test message from Sonar."); - - assertThat(server.getReceivedEmailSize(), is(1)); - SmtpMessage email = (SmtpMessage) server.getReceivedEmail().next(); - - assertThat(email.getHeaderValue("From"), is("Sonar ")); - assertThat(email.getHeaderValue("To"), is("")); - assertThat(email.getHeaderValue("Subject"), is("[SONAR] Test Message from Sonar")); - assertThat(email.getBody(), is("This is a test message from Sonar.")); - } - - @Test(expected = EmailException.class) - public void shouldThrowAnExceptionWhenUnableToSendTestEmail() throws Exception { - configure(); - server.stop(); - - channel.sendTestEmail("user@nowhere", "Test Message from Sonar", "This is a test message from Sonar."); - } - - @Test - public void shouldNotSendEmailWhenHostnameNotConfigured() throws Exception { - EmailMessage emailMessage = new EmailMessage() - .setTo("user@nowhere") - .setSubject("Foo") - .setMessage("Bar"); - channel.deliver(emailMessage); - assertThat(server.getReceivedEmailSize(), is(0)); - } - - @Test - public void shouldSendThreadedEmail() throws Exception { - configure(); - EmailMessage emailMessage = new EmailMessage() - .setMessageId("reviews/view/1") - .setFrom("Full Username") - .setTo("user@nowhere") - .setSubject("Review #3") - .setMessage("I'll take care of this violation."); - channel.deliver(emailMessage); - - assertThat(server.getReceivedEmailSize(), is(1)); - SmtpMessage email = (SmtpMessage) server.getReceivedEmail().next(); - - assertThat(email.getHeaderValue("In-Reply-To"), is("")); - assertThat(email.getHeaderValue("References"), is("")); - - assertThat(email.getHeaderValue("List-ID"), is("Sonar ")); - assertThat(email.getHeaderValue("List-Archive"), is("http://nemo.sonarsource.org")); - - assertThat(email.getHeaderValue("From"), is("Full Username ")); - assertThat(email.getHeaderValue("To"), is("")); - assertThat(email.getHeaderValue("Subject"), is("[SONAR] Review #3")); - assertThat(email.getBody(), is("I'll take care of this violation.")); - } - - @Test - public void shouldSendNonThreadedEmail() throws Exception { - configure(); - EmailMessage emailMessage = new EmailMessage() - .setTo("user@nowhere") - .setSubject("Foo") - .setMessage("Bar"); - channel.deliver(emailMessage); - - assertThat(server.getReceivedEmailSize(), is(1)); - SmtpMessage email = (SmtpMessage) server.getReceivedEmail().next(); - - assertThat(email.getHeaderValue("In-Reply-To"), nullValue()); - assertThat(email.getHeaderValue("References"), nullValue()); - - assertThat(email.getHeaderValue("List-ID"), is("Sonar ")); - assertThat(email.getHeaderValue("List-Archive"), is("http://nemo.sonarsource.org")); - - assertThat(email.getHeaderValue("From"), is("Sonar ")); - assertThat(email.getHeaderValue("To"), is("")); - assertThat(email.getHeaderValue("Subject"), is("[SONAR] Foo")); - assertThat(email.getBody(), is("Bar")); - } - - @Test - public void shouldNotThrowAnExceptionWhenUnableToSendEmail() throws Exception { - configure(); - server.stop(); - - EmailMessage emailMessage = new EmailMessage() - .setTo("user@nowhere") - .setSubject("Foo") - .setMessage("Bar"); - channel.deliver(emailMessage); - } - - private void configure() { - when(configuration.getSmtpHost()).thenReturn("localhost"); - when(configuration.getSmtpPort()).thenReturn(Integer.toString(port)); - when(configuration.getFrom()).thenReturn("server@nowhere"); - when(configuration.getPrefix()).thenReturn("[SONAR]"); - when(configuration.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org"); - } - -} diff --git a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailPluginTest.java b/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailPluginTest.java deleted file mode 100644 index 8ffa68364f8..00000000000 --- a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/EmailPluginTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email; - -import static org.hamcrest.Matchers.greaterThan; -import static org.junit.Assert.assertThat; - -import org.junit.Test; - -public class EmailPluginTest { - - @Test - public void testGetExtensions() { - assertThat(new EmailPlugin().getExtensions().size(), greaterThan(1)); - } - -} diff --git a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ChangesInReviewAssignedToMeTest.java b/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ChangesInReviewAssignedToMeTest.java deleted file mode 100644 index c74ce6ba098..00000000000 --- a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ChangesInReviewAssignedToMeTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email.reviews; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.notifications.Notification; -import org.sonar.api.notifications.NotificationDispatcher; - -public class ChangesInReviewAssignedToMeTest { - - private NotificationDispatcher.Context context; - private ChangesInReviewAssignedToMe dispatcher; - - @Before - public void setUp() { - context = mock(NotificationDispatcher.Context.class); - dispatcher = new ChangesInReviewAssignedToMe(); - } - - @Test - public void dispatchToOldAndNewAssignee() { - Notification notification = new Notification("review-assignee-changed") - .setFieldValue("author", "freddy") - .setFieldValue("old.assignee", "godin") - .setFieldValue("assignee", "simon"); - - dispatcher.dispatch(notification, context); - - verify(context).addUser("godin"); - verify(context).addUser("simon"); - verifyNoMoreInteractions(context); - } - - @Test - public void doNotDispatchToAuthorOfChanges() { - Notification notification = new Notification("review-assignee-changed") - .setFieldValue("author", "simon") - .setFieldValue("old.assignee", "simon") - .setFieldValue("assignee", "godin"); - - dispatcher.dispatch(notification, context); - - verify(context).addUser("godin"); - verifyNoMoreInteractions(context); - } - - @Test - public void shouldNotDispatch() { - Notification notification = new Notification("other"); - - dispatcher.dispatch(notification, context); - - verifyNoMoreInteractions(context); - } - -} diff --git a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ChangesInReviewCreatedByMeTest.java b/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ChangesInReviewCreatedByMeTest.java deleted file mode 100644 index a3fd7aa03b0..00000000000 --- a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ChangesInReviewCreatedByMeTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email.reviews; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.notifications.Notification; -import org.sonar.api.notifications.NotificationDispatcher; - -public class ChangesInReviewCreatedByMeTest { - - private NotificationDispatcher.Context context; - private ChangesInReviewCreatedByMe dispatcher; - - @Before - public void setUp() { - context = mock(NotificationDispatcher.Context.class); - dispatcher = new ChangesInReviewCreatedByMe(); - } - - @Test - public void dispatchToCreator() { - Notification notification = new Notification("review-comment-added") - .setFieldValue("author", "godin") - .setFieldValue("creator", "simon"); - - dispatcher.dispatch(notification, context); - - verify(context).addUser("simon"); - verifyNoMoreInteractions(context); - } - - @Test - public void doNotDispatchToAuthorOfChanges() { - Notification notification = new Notification("review-comment-added") - .setFieldValue("author", "simon") - .setFieldValue("creator", "simon"); - - dispatcher.dispatch(notification, context); - - verifyNoMoreInteractions(context); - } - - @Test - public void shouldNotDispatch() { - Notification notification = new Notification("other"); - - dispatcher.dispatch(notification, context); - - verifyNoMoreInteractions(context); - } - -} diff --git a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ReviewEmailTemplateTest.java b/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ReviewEmailTemplateTest.java deleted file mode 100644 index 6b64545eb5a..00000000000 --- a/plugins/sonar-email-plugin/src/test/java/org/sonar/plugins/email/reviews/ReviewEmailTemplateTest.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.email.reviews; - -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.database.model.User; -import org.sonar.api.notifications.Notification; -import org.sonar.api.security.UserFinder; -import org.sonar.plugins.email.EmailConfiguration; -import org.sonar.plugins.email.api.EmailMessage; - -public class ReviewEmailTemplateTest { - - private ReviewEmailTemplate template; - - @Before - public void setUp() { - EmailConfiguration configuration = mock(EmailConfiguration.class); - when(configuration.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org"); - UserFinder userFinder = mock(UserFinder.class); - when(userFinder.findByLogin(eq("freddy.mallet"))).thenReturn(new User().setName("Freddy Mallet")); - when(userFinder.findByLogin(eq("simon.brandhof"))).thenReturn(new User().setName("Simon Brandhof")); - when(userFinder.findByLogin(eq("evgeny.mandrikov"))).thenReturn(new User().setName("Evgeny Mandrikov")); - template = new ReviewEmailTemplate(configuration, userFinder); - } - - /** - *
-   * Subject: Review #1
-   * From: Freddy Mallet
-   * 
-   * Comment:
-   *   This is my first comment
-   * 
-   * --
-   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
-   * 
- */ - @Test - public void shouldFormatCommentAdded() { - Notification notification = new Notification("review-changed") - .setFieldValue("reviewId", "1") - .setFieldValue("author", "freddy.mallet") - .setFieldValue("old.comment", null) - .setFieldValue("new.comment", "This is my first comment"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("review/1")); - assertThat(message.getSubject(), is("Review #1")); - assertThat(message.getFrom(), is("Freddy Mallet")); - assertThat(message.getMessage(), is("Comment:\n This is my first comment\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); - } - - /** - *
-   * Subject: Review #1
-   * From: Freddy Mallet
-   * 
-   * Comment:
-   *   This is another comment
-   * Was:
-   *   This is my first comment
-   * 
-   * --
-   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
-   * 
- */ - @Test - public void shouldFormatCommentEdited() { - Notification notification = new Notification("review-changed") - .setFieldValue("reviewId", "1") - .setFieldValue("author", "freddy.mallet") - .setFieldValue("old.comment", "This is my first comment") - .setFieldValue("new.comment", "This is another comment"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("review/1")); - assertThat(message.getSubject(), is("Review #1")); - assertThat(message.getFrom(), is("Freddy Mallet")); - assertThat(message.getMessage(), is("Comment:\n This is another comment\nWas:\n This is my first comment\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); - } - - /** - *
-   * Subject: Review #1
-   * From: Freddy Mallet
-   * 
-   * Comment deleted, was:
-   *   This is deleted comment
-   *   
-   * --
-   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
-   * 
- */ - @Test - public void shouldFormatCommentDeleted() { - Notification notification = new Notification("review-changed") - .setFieldValue("reviewId", "1") - .setFieldValue("old.comment", "This is deleted comment") - .setFieldValue("new.comment", null) - .setFieldValue("author", "freddy.mallet"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("review/1")); - assertThat(message.getSubject(), is("Review #1")); - assertThat(message.getFrom(), is("Freddy Mallet")); - assertThat(message.getMessage(), is("Comment deleted, was:\n This is deleted comment\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); - } - - /** - *
-   * Subject: Review #1
-   * From: Freddy Mallet
-   * 
-   * Assignee: Evgeny Mandrikov
-   * 
-   * --
-   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
-   * 
- */ - @Test - public void shouldFormatAssigneed() { - Notification notification = new Notification("review-changed") - .setFieldValue("reviewId", "1") - .setFieldValue("author", "freddy.mallet") - .setFieldValue("old.assignee", null) - .setFieldValue("new.assignee", "evgeny.mandrikov"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("review/1")); - assertThat(message.getSubject(), is("Review #1")); - assertThat(message.getFrom(), is("Freddy Mallet")); - assertThat(message.getMessage(), is("Assignee: Evgeny Mandrikov\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); - } - - /** - *
-   * Subject: Review #1
-   * From: Freddy Mallet
-   * 
-   * Assignee: Simon Brandhof (was Evgeny Mandrikov)
-   * 
-   * --
-   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
-   * 
- */ - @Test - public void shouldFormatAssigneedToAnotherPerson() { - Notification notification = new Notification("review-changed") - .setFieldValue("reviewId", "1") - .setFieldValue("author", "freddy.mallet") - .setFieldValue("old.assignee", "evgeny.mandrikov") - .setFieldValue("new.assignee", "simon.brandhof"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("review/1")); - assertThat(message.getSubject(), is("Review #1")); - assertThat(message.getFrom(), is("Freddy Mallet")); - assertThat(message.getMessage(), is("Assignee: Simon Brandhof (was Evgeny Mandrikov)\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); - } - - /** - *
-   * Subject: Review #1
-   * From: Freddy Mallet
-   * 
-   * Assignee: (was Simon Brandhof)
-   * 
-   * --
-   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
-   * 
- */ - @Test - public void shouldFormatUnassigned() { - Notification notification = new Notification("review-changed") - .setFieldValue("reviewId", "1") - .setFieldValue("author", "freddy.mallet") - .setFieldValue("old.assignee", "simon.brandhof") - .setFieldValue("new.assignee", null); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("review/1")); - assertThat(message.getSubject(), is("Review #1")); - assertThat(message.getFrom(), is("Freddy Mallet")); - assertThat(message.getMessage(), is("Assignee: (was Simon Brandhof)\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); - } - - /** - *
-   * Subject: Review #1
-   * From: Sonar
-   * 
-   * Status: CLOSED (was OPEN)
-   * 
-   * --
-   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
-   * 
- */ - @Test - public void shouldFormatClosed() { - Notification notification = new Notification("review-changed") - .setFieldValue("reviewId", "1") - .setFieldValue("old.status", "OPEN") - .setFieldValue("new.status", "CLOSED"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("review/1")); - assertThat(message.getSubject(), is("Review #1")); - assertThat(message.getFrom(), nullValue()); - assertThat(message.getMessage(), is("Status: CLOSED (was OPEN)\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); - } - - /** - *
-   * Subject: Review #1
-   * From: Simon Brandhof
-   * 
-   * Status: REOPENED (was RESOLVED)
-   * Resolution: (was FIXED)
-   * 
-   * --
-   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
-   * 
- */ - @Test - public void shouldFormatReopened() { - Notification notification = new Notification("review-changed") - .setFieldValue("reviewId", "1") - .setFieldValue("old.resolution", "FIXED") - .setFieldValue("new.resolution", null) - .setFieldValue("old.status", "RESOLVED") - .setFieldValue("new.status", "REOPENED"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("review/1")); - assertThat(message.getSubject(), is("Review #1")); - assertThat(message.getFrom(), nullValue()); - assertThat(message.getMessage(), is("Status: REOPENED (was RESOLVED)\nResolution: (was FIXED)\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); - } - - /** - *
-   * Subject: Review #1
-   * From: Simon Brandhof
-   * 
-   * Status: RESOLVED (was OPEN)
-   * Resolution: FIXED
-   * 
-   * --
-   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
-   * 
- */ - @Test - public void shouldFormatResolvedAsFixed() { - Notification notification = new Notification("review-changed") - .setFieldValue("reviewId", "1") - .setFieldValue("author", "simon.brandhof") - .setFieldValue("old.status", "OPEN") - .setFieldValue("old.resolution", null) - .setFieldValue("new.status", "RESOLVED") - .setFieldValue("new.resolution", "FIXED"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("review/1")); - assertThat(message.getSubject(), is("Review #1")); - assertThat(message.getFrom(), is("Simon Brandhof")); - assertThat(message.getMessage(), is("Status: RESOLVED (was OPEN)\nResolution: FIXED\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); - } - - /** - *
-   * Subject: Review #1
-   * From: Simon Brandhof
-   * 
-   * Status: RESOLVED (was REOPENED)
-   * Resolution: FALSE-POSITIVE
-   * 
-   * --
-   * See it in Sonar: http://nemo.sonarsource.org/review/view/1
-   * 
- */ - @Test - public void shouldFormatResolvedAsFalsePositive() { - Notification notification = new Notification("review-changed") - .setFieldValue("reviewId", "1") - .setFieldValue("author", "freddy.mallet") - .setFieldValue("old.status", "REOPENED") - .setFieldValue("old.resolution", null) - .setFieldValue("new.status", "RESOLVED") - .setFieldValue("new.resolution", "FALSE-POSITIVE"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("review/1")); - assertThat(message.getSubject(), is("Review #1")); - assertThat(message.getFrom(), is("Freddy Mallet")); - assertThat(message.getMessage(), is("Status: RESOLVED (was REOPENED)\nResolution: FALSE-POSITIVE\n\n--\nSee it in Sonar: http://nemo.sonarsource.org/review/view/1\n")); - } - - @Test - public void shouldNotFormat() { - Notification notification = new Notification("other"); - EmailMessage message = template.format(notification); - assertThat(message, nullValue()); - } - - @Test - public void shouldReturnFullNameOrLogin() { - assertThat(template.getUserFullName("freddy.mallet"), is("Freddy Mallet")); - assertThat(template.getUserFullName("deleted"), is("deleted")); - } - -} diff --git a/plugins/sonar-i18n-en-plugin/src/main/resources/org/sonar/i18n/core.properties b/plugins/sonar-i18n-en-plugin/src/main/resources/org/sonar/i18n/core.properties index ecddbb9f9a1..cf1f4d0736d 100644 --- a/plugins/sonar-i18n-en-plugin/src/main/resources/org/sonar/i18n/core.properties +++ b/plugins/sonar-i18n-en-plugin/src/main/resources/org/sonar/i18n/core.properties @@ -291,6 +291,7 @@ users.page=Users violations.page=Violations violations_drilldown.page=Violations drilldown update_center.page=Update Center +email_configuration.page=Email configuration org.sonar.plugins.core.hotspots.GwtHotspots.page=Hotspots org.sonar.plugins.core.duplicationsviewer.DuplicationsViewer.page=Duplications @@ -635,6 +636,33 @@ rules_configuration.x_rules_have_been_activated={0} rules have been activated. rules_configuration.x_rules_have_been_deactivated={0} rules have been deactivated. +#------------------------------------------------------------------------------ +# +# EMAIL CONFIGURATION +# +#------------------------------------------------------------------------------ +email_configuration.smtp_host=SMTP host +email_configuration.smtp_port=SMTP port +email_configuration.use_tls=Use TLS +email_configuration.smtp_username=SMTP username +email_configuration.smtp_password=SMTP password +email_configuration.from_address=From address +email_configuration.email_prefix=Email prefix +email_configuration.test.title=Send Test Email +email_configuration.test.to_address=To +email_configuration.test.to_address_required=You must provide address where to send test email +email_configuration.test.subject=Subject +email_configuration.test.subject_text=Test Message from Sonar +email_configuration.test.message=Message +email_configuration.test.message_text=This is a test message from Sonar +email_configuration.test.send=Send +email_configuration.test.email_was_sent_to_x=Email was sent to {0} + +notification.channel.EmailNotificationChannel=Email +notification.dispatcher.ChangesInReviewAssignedToMe=Changes in review assigned to me +notification.dispatcher.ChangesInReviewCreatedByMe=Changes in review created by me + + #------------------------------------------------------------------------------ # # ALERTS diff --git a/pom.xml b/pom.xml index 857584c86a2..0c17b60efcf 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ plugins/sonar-squid-java-plugin plugins/sonar-design-plugin plugins/sonar-i18n-en-plugin - plugins/sonar-email-plugin + plugins/sonar-email-notifications-plugin diff --git a/sonar-application/pom.xml b/sonar-application/pom.xml index 407cb8aeefb..9e9876e467b 100644 --- a/sonar-application/pom.xml +++ b/sonar-application/pom.xml @@ -210,7 +210,7 @@ org.codehaus.sonar.plugins - sonar-email-plugin + sonar-email-notifications-plugin ${project.version} runtime diff --git a/sonar-server/pom.xml b/sonar-server/pom.xml index 6f6f74371af..43ffeae91d0 100644 --- a/sonar-server/pom.xml +++ b/sonar-server/pom.xml @@ -456,7 +456,7 @@ org.codehaus.sonar.plugins - sonar-email-plugin + sonar-email-notifications-plugin ${project.version} provided diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/email_configuration_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/email_configuration_controller.rb index 163ece76c50..3d877da0921 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/email_configuration_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/email_configuration_controller.rb @@ -48,10 +48,11 @@ class EmailConfigurationController < ApplicationController subject = params[:subject] message = params[:message] if to_address.blank? - flash[:notice] = 'You must provide address where to send test email' + flash[:notice] = message('email_configuration.test.to_address_required') else begin - java_facade.getComponentByClassname('email', 'org.sonar.plugins.email.EmailNotificationChannel').sendTestEmail(to_address, subject, message) + java_facade.getComponentByClassname('emailnotifications', 'org.sonar.plugins.emailnotifications.EmailNotificationChannel').sendTestEmail(to_address, subject, message) + flash[:notice] = message('email_configuration.test.email_was_sent_to_x', :params => [to_address]) rescue Exception => e flash[:error] = e.message end @@ -62,7 +63,7 @@ class EmailConfigurationController < ApplicationController private def configuration - java_facade.getComponentByClassname('email', 'org.sonar.plugins.email.EmailConfiguration').class + java_facade.getComponentByClassname('emailnotifications', 'org.sonar.plugins.emailnotifications.EmailConfiguration').class end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb index 1bf9a705b24..f91269107bf 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb @@ -29,9 +29,9 @@

Change password


<% form_tag( {:action => 'change_password' }, :id => 'pass_form_tag', :name => 'pass_form_tag') do -%> - - -
+ + + @@ -40,7 +40,7 @@ - @@ -49,7 +49,7 @@ - @@ -58,15 +58,15 @@ -
+
+
-
- <%= submit_tag 'Change password' %> +
+
+ <%= submit_tag 'Change password' %> <% end %> - + <% end -%>
@@ -77,12 +77,12 @@ <% for channel in @channels %> - <%= channel.getKey() %> + <%= message('notification.channel.' + channel.getKey()) -%> <% end %> <% for dispatcher in @dispatchers %> - <%= dispatcher.getKey() %> + <%= message('notification.dispatcher.' + dispatcher.getKey()) -%> <% for channel in @channels diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/email_configuration/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/email_configuration/index.html.erb index d59ec3a089b..a0f53d63264 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/email_configuration/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/email_configuration/index.html.erb @@ -1,9 +1,10 @@ -

Email configuration

+

<%= message('email_configuration.page') -%>

+
<% form_tag({:action => 'save'}) do -%>
- + @@ -13,7 +14,7 @@
- + @@ -23,7 +24,7 @@
- + @@ -33,7 +34,7 @@
- + @@ -43,7 +44,7 @@
- + @@ -53,7 +54,7 @@
- + @@ -63,7 +64,7 @@
- + @@ -71,16 +72,18 @@
- <%= submit_tag %> +
+ <%= submit_tag message('save') %> <% end -%>
-

Send Test Email

+

<%= message('email_configuration.test.title') -%>

+
<% form_tag({:action => 'send_test_email'}) do -%>
- + @@ -89,22 +92,23 @@
- + - <%= text_field_tag 'subject', 'Test Message from Sonar' %> + <%= text_field_tag 'subject', message('email_configuration.test.subject_text') %>
- + - <%= text_area_tag 'message', 'This is a test message from Sonar.' %> + <%= text_area_tag 'message', message('email_configuration.test.message_text') %>
- <%= submit_tag 'Send' %> +
+ <%= submit_tag message('email_configuration.test.send') %> <% end -%> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb index 1ac79bf85d8..fbc097c14a6 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb @@ -86,6 +86,7 @@ if update_center_activated=='true' %>
  • <%= message('update_center.page') -%>
  • <% end %> +
  • <%= message('email_configuration.page') -%>
  • <% end %> <% end %> -- cgit v1.2.3