diff options
author | Evgeny Mandrikov <mandrikov@gmail.com> | 2011-07-18 16:41:00 +0400 |
---|---|---|
committer | Evgeny Mandrikov <mandrikov@gmail.com> | 2011-07-18 23:34:06 +0400 |
commit | ded6ace3a7761468a97b6ac7fc7b924cd1147b96 (patch) | |
tree | 053dd641fd2e2457e118c50ca006cd0478d1f9b4 | |
parent | ba62b82ea636be85d3c3c316174f2c8e4ad551ff (diff) | |
download | sonarqube-ded6ace3a7761468a97b6ac7fc7b924cd1147b96.tar.gz sonarqube-ded6ace3a7761468a97b6ac7fc7b924cd1147b96.zip |
SONAR-2600,SONAR-2601 Add ability to send emails
Add simple page with SMTP configuration and with ability to send test
email. When SMTP configured - send notifications via email.
9 files changed, 488 insertions, 76 deletions
diff --git a/sonar-server/pom.xml b/sonar-server/pom.xml index 53441136766..df611dabce4 100644 --- a/sonar-server/pom.xml +++ b/sonar-server/pom.xml @@ -155,6 +155,11 @@ <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-util</artifactId> </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-email</artifactId> + <version>1.2</version> + </dependency> <!-- unit tests --> <dependency> @@ -162,6 +167,12 @@ <artifactId>sonar-testing-harness</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>dumbster</groupId> + <artifactId>dumbster</artifactId> + <version>1.6</version> + <scope>test</scope> + </dependency> </dependencies> diff --git a/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailConfiguration.java b/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailConfiguration.java new file mode 100644 index 00000000000..e16e536cd0c --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailConfiguration.java @@ -0,0 +1,81 @@ +/* + * 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.server.notifications.email; + +import org.apache.commons.configuration.Configuration; +import org.sonar.api.ServerComponent; + +/** + * Ruby uses constants from this class. + * + * @since 2.10 + */ +public class EmailConfiguration implements ServerComponent { + + 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); + } + +} diff --git a/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailMessage.java b/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailMessage.java index c64b3b3e175..c2227e6506b 100644 --- a/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailMessage.java +++ b/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailMessage.java @@ -19,6 +19,8 @@ */ package org.sonar.server.notifications.email; +import org.apache.commons.lang.builder.ToStringBuilder; + import java.io.Serializable; /** @@ -107,4 +109,9 @@ public class EmailMessage implements Serializable { return messageId; } + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this).toString(); + } + } diff --git a/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailNotificationChannel.java b/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailNotificationChannel.java index a0b12e14a13..7c07f56f063 100644 --- a/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailNotificationChannel.java +++ b/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailNotificationChannel.java @@ -19,9 +19,14 @@ */ package org.sonar.server.notifications.email; -import org.codehaus.plexus.util.StringUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.mail.Email; +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.jpa.session.DatabaseSessionFactory; import org.sonar.server.notifications.Notification; import org.sonar.server.notifications.NotificationChannel; @@ -41,14 +46,27 @@ public class EmailNotificationChannel extends NotificationChannel { private static final Logger LOG = LoggerFactory.getLogger(EmailNotificationChannel.class); - private static final String FROM_DEFAULT = "Sonar"; - private static final String SUBJECT_PREFIX = "[Sonar]"; + /** + * @see Email#setSocketConnectionTimeout(int) + * @see Email#setSocketTimeout(int) + */ + private static final int SOCKET_TIMEOUT = 30000; + + private static final String FROM_NAME_DEFAULT = "Sonar"; private static final String SUBJECT_DEFAULT = "Notification"; + private EmailConfiguration configuration; private EmailMessageTemplate[] templates; + private DatabaseSessionFactory sessionFactory; - public EmailNotificationChannel(EmailMessageTemplate[] templates) { + public EmailNotificationChannel(EmailConfiguration configuration, EmailMessageTemplate[] templates, DatabaseSessionFactory sessionFactory) { + this.configuration = configuration; this.templates = templates; + this.sessionFactory = sessionFactory; + } + + private User getUserById(Integer id) { + return sessionFactory.getSession().getEntity(User.class, id); } @Override @@ -56,7 +74,8 @@ public class EmailNotificationChannel extends NotificationChannel { for (EmailMessageTemplate template : templates) { EmailMessage email = template.format(notification); if (email != null) { - email.setTo(userId.toString()); // TODO should be valid email@address + User user = getUserById(userId); + email.setTo(user.getEmail()); return email; } } @@ -65,47 +84,68 @@ public class EmailNotificationChannel extends NotificationChannel { @Override public void deliver(Serializable notificationData) { - EmailMessage email = (EmailMessage) notificationData; - LOG.info("Email:\n{}", create(email)); + if (StringUtils.isBlank(configuration.getSmtpHost())) { + LOG.warn("SMTP host was not configured - email will not be sent"); + return; + } + try { + send((EmailMessage) notificationData); + } catch (EmailException e) { + LOG.error("Unable to send email", e); + } } - /** - * Visibility has been relaxed for tests. - */ - String create(EmailMessage email) { + private void send(EmailMessage emailMessage) throws EmailException { + LOG.info("Sending email: {}", emailMessage); // TODO - String serverUrl = "http://nemo.sonarsource.org"; String domain = "nemo.sonarsource.org"; String listId = "<sonar." + domain + ">"; - String from = StringUtils.defaultString(email.getFrom(), FROM_DEFAULT) + " <noreply@" + domain + ">"; - String subject = SUBJECT_PREFIX + " " + StringUtils.defaultString(email.getSubject(), SUBJECT_DEFAULT); - String permalink = null; - StringBuilder sb = new StringBuilder(); - if (StringUtils.isNotEmpty(email.getMessageId())) { - subject = "Re: " + subject; - String messageId = "<" + email.getMessageId() + "@" + domain + ">"; - appendHeader(sb, "Message-Id", messageId); - appendHeader(sb, "In-Reply-To", messageId); - appendHeader(sb, "References", messageId); - permalink = serverUrl + '/' + email.getMessageId(); + String serverUrl = "http://nemo.sonarsource.org"; + + SimpleEmail email = new SimpleEmail(); + /* + * 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() + "@" + domain + ">"; + email.addHeader("In-Reply-To", messageId); + email.addHeader("References", messageId); } - appendHeader(sb, "List-Id", listId); - appendHeader(sb, "List-Archive", serverUrl); - appendHeader(sb, "From", from); - appendHeader(sb, "To", email.getTo()); - appendHeader(sb, "Subject", subject); - sb.append('\n') - .append(email.getMessage()).append('\n'); - if (permalink != null) { - sb.append('\n') - .append("--\n") - .append("View it in Sonar: ").append(permalink); + // Set headers for proper filtering + email.addHeader("List-Id", listId); + email.addHeader("List-Archive", serverUrl); + // 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()); } - return sb.toString(); + email.setSocketConnectionTimeout(SOCKET_TIMEOUT); + email.setSocketTimeout(SOCKET_TIMEOUT); + email.send(); } - private void appendHeader(StringBuilder sb, String header, String value) { - sb.append(header).append(": ").append(value).append('\n'); + /** + * 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/sonar-server/src/main/java/org/sonar/server/notifications/reviews/CommentOnReviewEmailTemplate.java b/sonar-server/src/main/java/org/sonar/server/notifications/reviews/CommentOnReviewEmailTemplate.java index eb982500128..460db32c9a4 100644 --- a/sonar-server/src/main/java/org/sonar/server/notifications/reviews/CommentOnReviewEmailTemplate.java +++ b/sonar-server/src/main/java/org/sonar/server/notifications/reviews/CommentOnReviewEmailTemplate.java @@ -35,7 +35,7 @@ public class CommentOnReviewEmailTemplate extends EmailMessageTemplate { EmailMessage email = new EmailMessage() .setFrom(event.getAuthor().getName()) .setMessageId("review/" + event.getReview().getId()) - .setSubject(event.getReview().getTitle()) + .setSubject("Review #" + event.getReview().getId()) .setMessage(event.getComment()); return email; } diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 160602d419e..49bcf2d6aa4 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -58,6 +58,7 @@ import org.sonar.server.mavendeployer.MavenRepository; import org.sonar.server.notifications.NotificationManager; import org.sonar.server.notifications.NotificationQueue; import org.sonar.server.notifications.NotificationService; +import org.sonar.server.notifications.email.EmailConfiguration; import org.sonar.server.notifications.email.EmailNotificationChannel; import org.sonar.server.notifications.reviews.CommentOnReviewAssignedToMe; import org.sonar.server.notifications.reviews.CommentOnReviewCreatedByMe; @@ -196,7 +197,8 @@ public final class Platform { servicesContainer.as(Characteristics.CACHE).addComponent(NotificationService.class); servicesContainer.as(Characteristics.CACHE).addComponent(NotificationManager.class); servicesContainer.as(Characteristics.CACHE).addComponent(ReviewsNotificationManager.class); - // FIXME next four lines here just for tests: + // FIXME next five lines here just for tests: + servicesContainer.as(Characteristics.CACHE).addComponent(EmailConfiguration.class); servicesContainer.as(Characteristics.CACHE).addComponent(EmailNotificationChannel.class); servicesContainer.as(Characteristics.CACHE).addComponent(CommentOnReviewEmailTemplate.class); servicesContainer.as(Characteristics.CACHE).addComponent(CommentOnReviewAssignedToMe.class); 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 new file mode 100644 index 00000000000..77c3172f3b2 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/email_configuration_controller.rb @@ -0,0 +1,64 @@ +# +# Sonar, entreprise quality control 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 +# +class EmailConfigurationController < ApplicationController + + SECTION=Navigation::SECTION_CONFIGURATION + before_filter :admin_required + + EmailConfiguration = org.sonar.server.notifications.email.EmailConfiguration + + def index + @smtp_host = Property.value(EmailConfiguration::SMTP_HOST, nil, EmailConfiguration::SMTP_HOST_DEFAULT) + @smtp_port = Property.value(EmailConfiguration::SMTP_PORT, nil, EmailConfiguration::SMTP_PORT_DEFAULT) + @smtp_use_tls = Property.value(EmailConfiguration::SMTP_USE_TLS, nil, EmailConfiguration::SMTP_USE_TLS_DEFAULT) == 'true' + @smtp_username = Property.value(EmailConfiguration::SMTP_USERNAME, nil, EmailConfiguration::SMTP_USERNAME_DEFAULT) + @smtp_password = Property.value(EmailConfiguration::SMTP_PASSWORD, nil, EmailConfiguration::SMTP_PASSWORD_DEFAULT) + @email_from = Property.value(EmailConfiguration::FROM, nil, EmailConfiguration::FROM_DEFAULT) + @email_prefix = Property.value(EmailConfiguration::PREFIX, nil, EmailConfiguration::PREFIX_DEFAULT) + end + + def save + Property.set(EmailConfiguration::SMTP_HOST, params[:smtp_host]) + Property.set(EmailConfiguration::SMTP_PORT, params[:smtp_port]) + Property.set(EmailConfiguration::SMTP_USE_TLS, params[:smtp_use_tls] == 'true') + Property.set(EmailConfiguration::SMTP_USERNAME, params[:smtp_username]) + Property.set(EmailConfiguration::SMTP_PASSWORD, params[:smtp_password]) + Property.set(EmailConfiguration::FROM, params[:email_from]) + Property.set(EmailConfiguration::PREFIX, params[:email_prefix]) + redirect_to :action => 'index' + end + + def send_test_email + to_address = params[:to_address] + subject = params[:subject] + message = params[:message] + if to_address.blank? + flash[:notice] = 'You must provide address where to send test email' + else + begin + java_facade.getCoreComponentByClassname('org.sonar.server.notifications.email.EmailNotificationChannel').sendTestEmail(to_address, subject, message) + rescue Exception => e + flash[:error] = e.message + end + end + redirect_to :action => 'index' + end + +end 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 new file mode 100644 index 00000000000..d59ec3a089b --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/email_configuration/index.html.erb @@ -0,0 +1,110 @@ +<h1>Email configuration</h1> +<% form_tag({:action => 'save'}) do -%> + <table> + <tr> + <td nowrap> + <label for="smtp_host"><b>SMTP Host:</b></label> + </td> + <td class="sep"> </td> + <td align="left"> + <%= text_field_tag 'smtp_host', @smtp_host %> + </td> + </tr> + + <tr> + <td nowrap> + <label for="smtp_port"><b>SMTP Port:</b></label> + </td> + <td class="sep"> </td> + <td align="left"> + <%= text_field_tag 'smtp_port', @smtp_port %> + </td> + </tr> + + <tr> + <td nowrap> + <label for="smtp_port"><b>Use TLS:</b></label> + </td> + <td class="sep"> </td> + <td align="left"> + <%= check_box_tag 'smtp_use_tls', 'true', @smtp_use_tls %> + </td> + </tr> + + <tr> + <td nowrap> + <label for="smtp_username"><b>SMTP Username:</b></label> + </td> + <td class="sep"> </td> + <td align="left"> + <%= text_field_tag 'smtp_username', @smtp_username %> + </td> + </tr> + + <tr> + <td nowrap> + <label for="smtp_password"><b>SMTP Password:</b></label> + </td> + <td class="sep"> </td> + <td align="left"> + <%= password_field_tag 'smtp_password', @smtp_password %> + </td> + </tr> + + <tr> + <td nowrap> + <label for="email_from"><b>From address:</b></label> + </td> + <td class="sep"> </td> + <td align="left"> + <%= text_field_tag 'email_from', @email_from %> + </td> + </tr> + + <tr> + <td nowrap> + <label for="email_prefix"><b>Email prefix:</b></label> + </td> + <td class="sep"> </td> + <td align="left"> + <%= text_field_tag 'email_prefix', @email_prefix %> + </td> + </tr> + </table> + <%= submit_tag %> +<% end -%> +<br/> + +<h1>Send Test Email</h1> +<% form_tag({:action => 'send_test_email'}) do -%> + <table> + <tr> + <td nowrap> + <label for="to_address"><b>To:</b></label> + </td> + <td class="sep"> </td> + <td align="left"> + <%= text_field_tag 'to_address', current_user.email %> + </td> + </tr> + <tr> + <td nowrap> + <label for="subject"><b>Subject:</b></label> + </td> + <td class="sep"> </td> + <td align="left"> + <%= text_field_tag 'subject', 'Test Message from Sonar' %> + </td> + </tr> + <tr> + <td nowrap> + <label for="message"><b>Message:</b></label> + </td> + <td class="sep"> </td> + <td align="left"> + <%= text_area_tag 'message', 'This is a test message from Sonar.' %> + </td> + </tr> + <table> + <%= submit_tag 'Send' %> +<% end -%> diff --git a/sonar-server/src/test/java/org/sonar/server/notifications/email/EmailNotificationChannelTest.java b/sonar-server/src/test/java/org/sonar/server/notifications/email/EmailNotificationChannelTest.java index 4c9c3544f4d..0b51f3e989b 100644 --- a/sonar-server/src/test/java/org/sonar/server/notifications/email/EmailNotificationChannelTest.java +++ b/sonar-server/src/test/java/org/sonar/server/notifications/email/EmailNotificationChannelTest.java @@ -20,63 +20,160 @@ package org.sonar.server.notifications.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 com.dumbster.smtp.SimpleSmtpServer; +import com.dumbster.smtp.SmtpMessage; +import org.apache.commons.mail.EmailException; +import org.junit.After; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; +import java.io.IOException; +import java.net.ServerSocket; + 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() { - channel = new EmailNotificationChannel(null); + 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 <server@nowhere>")); + assertThat(email.getHeaderValue("To"), is("<user@nowhere>")); + 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 shouldCreateEmail() { - EmailMessage email = new EmailMessage() + 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("Evgeny Mandrikov") - .setTo("simon.brandhof@sonarcource.com") + .setFrom("Full Username") + .setTo("user@nowhere") .setSubject("Review #3") .setMessage("I'll take care of this violation."); - String expected = "" + - "Message-Id: <reviews/view/1@nemo.sonarsource.org>\n" + - "In-Reply-To: <reviews/view/1@nemo.sonarsource.org>\n" + - "References: <reviews/view/1@nemo.sonarsource.org>\n" + - "List-Id: <sonar.nemo.sonarsource.org>\n" + - "List-Archive: http://nemo.sonarsource.org\n" + - "From: Evgeny Mandrikov <noreply@nemo.sonarsource.org>\n" + - "To: simon.brandhof@sonarcource.com\n" + - "Subject: Re: [Sonar] Review #3\n" + - "\n" + - "I'll take care of this violation.\n" + - "\n" + - "--\n" + - "View it in Sonar: http://nemo.sonarsource.org/reviews/view/1"; - String message = channel.create(email); - System.out.println(message); - assertThat(message, is(expected)); + channel.deliver(emailMessage); + + assertThat(server.getReceivedEmailSize(), is(1)); + SmtpMessage email = (SmtpMessage) server.getReceivedEmail().next(); + + assertThat(email.getHeaderValue("In-Reply-To"), is("<reviews/view/1@nemo.sonarsource.org>")); + assertThat(email.getHeaderValue("References"), is("<reviews/view/1@nemo.sonarsource.org>")); + + assertThat(email.getHeaderValue("List-Id"), is("<sonar.nemo.sonarsource.org>")); + assertThat(email.getHeaderValue("List-Archive"), is("http://nemo.sonarsource.org")); + + assertThat(email.getHeaderValue("From"), is("Full Username <server@nowhere>")); + assertThat(email.getHeaderValue("To"), is("<user@nowhere>")); + assertThat(email.getHeaderValue("Subject"), is("[SONAR] Review #3")); + assertThat(email.getBody(), is("I'll take care of this violation.")); } @Test - public void shouldCreateDefaultEmail() { - EmailMessage email = new EmailMessage() - .setTo("simon.brandhof@sonarcource.com") - .setMessage("Message"); - String expected = "" + - "List-Id: <sonar.nemo.sonarsource.org>\n" + - "List-Archive: http://nemo.sonarsource.org\n" + - "From: Sonar <noreply@nemo.sonarsource.org>\n" + - "To: simon.brandhof@sonarcource.com\n" + - "Subject: [Sonar] Notification\n" + - "\n" + - "Message\n"; - String message = channel.create(email); - System.out.println(message); - assertThat(message, is(expected)); + public void shouldSendNonThreadedEmail() { + 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.nemo.sonarsource.org>")); + assertThat(email.getHeaderValue("List-Archive"), is("http://nemo.sonarsource.org")); + + assertThat(email.getHeaderValue("From"), is("Sonar <server@nowhere>")); + assertThat(email.getHeaderValue("To"), is("<user@nowhere>")); + assertThat(email.getHeaderValue("Subject"), is("[SONAR] Foo")); + assertThat(email.getBody(), is("Bar")); + } + + @Test + public void shouldNotThrowAnExceptionWhenUnableToSendEmail() { + 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]"); } } |