Skip to content
Permalink
Browse files
JENKINS-7824: Add configurable emails to assignees when assigning a
failure
  • Loading branch information
ninian committed Aug 24, 2014
1 parent 0dd4449 commit a042eaaa28720855a67b45f87efd319966e9ce60
Showing 12 changed files with 311 additions and 1 deletion.
10 pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.490</version>
<version>1.509.4</version>
</parent>

<artifactId>claim</artifactId>
@@ -34,6 +34,14 @@
<url>http://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>mailer</artifactId>
<version>1.5</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>


@@ -13,6 +13,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.mail.MessagingException;
import javax.servlet.ServletException;

import org.acegisecurity.Authentication;
@@ -50,6 +51,8 @@ public String getIconFileName() {
public String getUrlName() {
return "claim";
}

abstract String getUrl();

public void doClaim(StaplerRequest req, StaplerResponse resp)
throws ServletException, IOException {
@@ -71,7 +74,15 @@ public void doClaim(StaplerRequest req, StaplerResponse resp)
boolean sticky = req.getSubmittedForm().getBoolean("sticky");
if (StringUtils.isEmpty(reason)) reason = null;
claim(name, reason, currentUser, sticky);
try {
ClaimEmailer.sendEmailIfConfigured(User.get(name, false, Collections.EMPTY_MAP), currentUser, owner.toString(), reason, getUrl());
} catch (MessagingException e) {
LOGGER.log(Level.WARNING, "Exception encountered sending assignment email: " + e.getMessage());
} catch (InterruptedException e) {
LOGGER.log(Level.WARNING, "Interrupted when sending assignment email",e);
}
owner.save();

resp.forwardToPreviousPage(req);
}

@@ -220,5 +231,6 @@ public boolean isSelfAssigned() {
}

public abstract String getNoun();


}
@@ -30,4 +30,9 @@ public Object readResolve() throws ObjectStreamException {
return this;
}

@Override
String getUrl() {
return owner.getUrl();
}

}
@@ -0,0 +1,61 @@
package hudson.plugins.claim;

import hudson.Extension;
import jenkins.model.GlobalConfiguration;
import net.sf.json.JSONObject;

import org.kohsuke.stapler.StaplerRequest;

@Extension
public class ClaimConfig extends GlobalConfiguration {

public ClaimConfig() {
load();
}

/**
* Whether we want to send emails to the assignee when items are claimed/assigned
*/
private boolean sendEmails;


/**
* This human readable name is used in the configuration screen.
*/
public String getDisplayName() {
return "Claim";
}

@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
// To persist global configuration information,
// set that to properties and call save().
sendEmails = formData.getBoolean("sendEmails");
save();
return super.configure(req,formData);
}

/**
* This method returns true if the global configuration says we should send mails on build claims
* @return true if configuration is that we send emails for claims, false otherwise
*/
public boolean getSendEmails() {
return sendEmails;
}

/**
* Set whether we should send emails
* @param val the setting to use
*/
public void setSendEmails(boolean val) {
sendEmails = val;
}

/**
* get the current claim configuration
* @return the global claim configuration
*/
public static ClaimConfig get() {
return GlobalConfiguration.all().get(ClaimConfig.class);
}
}
@@ -0,0 +1,124 @@
package hudson.plugins.claim;

import hudson.model.User;
import hudson.tasks.Mailer;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.mail.Address;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import jenkins.model.JenkinsLocationConfiguration;
/**
* Email utility class to allow sending of emails using the setup of the mailer plug-in to do so.
* If the mailer plug-in is not installed, then no emails are sent
*
*
*/
public class ClaimEmailer {

private static final Logger LOGGER = Logger.getLogger("claim-plugin");

private static final boolean mailerLoaded = isMailerLoaded();

private static boolean isMailerLoaded () {
boolean ret = true;
try {
new Mailer.DescriptorImpl();
} catch (Throwable e) {
LOGGER.warning("Mailer plugin is not installed. Mailer plugin must be installed if you want to send emails");
ret = false;
}
return ret;
}

/**
* Send an email to the assignee indicating that the given build has been assigned
* @param assignee the user assigned the failed build
* @param assignedBy the user assigning the build
* @param build the build/action which has been assigned
* @param reason the reason given for the assignment
* @param URL the URL the user can view for the assigned build
* @throws MessagingException if there has been some problem with sending the email
* @throws IOException if there is an IO problem when sending the mail
* @throws InterruptedException if the send operation is interrupted
*/
public static void sendEmailIfConfigured (User assignee, String assignedBy, String build, String reason, String URL) throws MessagingException, IOException, InterruptedException {

ClaimConfig config = ClaimConfig.get();
if (config.getSendEmails() && mailerLoaded) {
MimeMessage msg = createMessage(assignee, assignedBy, build, reason, URL);
Transport.send(msg);
}
}

private static MimeMessage createMessage(User assignee, String assignedBy, String build, String reason, String URL)
throws MessagingException, IOException, InterruptedException {
MimeMessage msg = null;
// create Session
final Mailer.DescriptorImpl mailDescriptor = new Mailer.DescriptorImpl();
msg = createMimeMessage(mailDescriptor);

msg.setSentDate(new Date());
msg.setSubject(Messages.ClaimEmailer_Subject(build),mailDescriptor.getCharset());
//TODO configurable formatting, through email-ext plugin
final String text = Messages.ClaimEmailer_Text(build, assignedBy) +
System.getProperty("line.separator") + Messages.ClaimEmailer_Reason(reason) +
System.getProperty("line.separator") + System.getProperty("line.separator") +
Messages.ClaimEmailer_Details(JenkinsLocationConfiguration.get().getUrl() + URL);

msg.setText(text, mailDescriptor.getCharset());
msg.setRecipient(RecipientType.TO, getUserEmail(assignee,mailDescriptor));

return msg;
}

/**
* Creates MimeMessage using the mailer plugin for jenkins.
*
* @param mailDescriptor a reference to the mailer plugin from which we can get mailing parameters
* @return mimemessage a message which can be emailed
* @throws MessagingException
* @throws UnsupportedEncodingException
* @throws AddressException
*
*/
private static MimeMessage createMimeMessage(final Mailer.DescriptorImpl mailDescriptor) throws AddressException, UnsupportedEncodingException, MessagingException {
MimeMessage ret = new MimeMessage(mailDescriptor.createSession());
ret.setFrom(Mailer.StringToAddress(JenkinsLocationConfiguration.get().getAdminAddress(), mailDescriptor.getCharset()));
return ret;
}

/**
* Returns the email address of a given user.
*
* @param user the user
* @param mailDescriptor the descriptor allowing us to access mail config
* @return email address for this user, null if none can be derived
*/
private static Address getUserEmail(User user, Mailer.DescriptorImpl mailDescriptor) {
if (user != null) {
try {
final Mailer.UserProperty mailProperty = user
.getProperty(Mailer.UserProperty.class);
if (mailProperty != null && mailProperty.getAddress() != null) {
return new InternetAddress(mailProperty.getAddress());
}
return new InternetAddress(user.getId() + mailDescriptor.getDefaultSuffix());
} catch (AddressException e) {
LOGGER.log(Level.WARNING, "Cannot get email address for user " + user.getId(), e);
}
}
return null;
}

}
@@ -26,4 +26,9 @@ public String getNoun() {
return Messages.ClaimTestAction_Noun();
}

@Override
String getUrl() {
return owner.getURL();
}

}
@@ -57,6 +57,10 @@ public static class Data extends TestResultAction.Data implements Saveable {
public Data(AbstractBuild<?,?> build) {
this.build = build;
}

public String getURL() {
return build.getUrl();
}

@Override
public List<TestAction> getTestAction(TestObject testObject) {
@@ -0,0 +1,7 @@
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<f:section title="Claim">
<f:entry title="${%SendEmails}" field="sendEmails" help="/plugin/claim/help-sendEmails.html">
<f:checkbox />
</f:entry>
</f:section>
</j:jelly>
@@ -0,0 +1 @@
SendEmails=Send emails when assigning/claiming builds
@@ -15,3 +15,8 @@ ClaimTestAction.DisplayName=Claim Test
ClaimTestAction.Noun=test

ClaimTestDataPublisher.DisplayName=Allow claiming of failed tests

ClaimEmailer.Subject=Claim/Assignment for {0}
ClaimEmailer.Text=Build {0} was assigned to you by {1}.
ClaimEmailer.Details=See {0} for further details
ClaimEmailer.Reason=Reason: {0}
@@ -0,0 +1,3 @@
<div>
If selected, an email is sent to the assignee when a build is claimed or assigned. To enable sending emails, you need to also install the email-ext plugin
</div>
@@ -0,0 +1,75 @@
package hudson.plugins.claim;

import hudson.model.UserProperty;
import hudson.model.User;
import hudson.tasks.Mailer;

import java.util.Collections;

import javax.mail.Address;
import javax.mail.internet.InternetAddress;

import jenkins.model.JenkinsLocationConfiguration;

import org.junit.Test;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.mock_javamail.Mailbox;

public class ClaimEmailerTest extends HudsonTestCase {

/*
* Test that no mail is sent if mail sending is not configured
*/
@Test
public void testSendEmailNotConfigured() throws Exception {

JenkinsLocationConfiguration.get().setAdminAddress("test <test@test.com>");
ClaimConfig config = ClaimConfig.get();
config.setSendEmails(false);

String recipient = "assignee <assignee@test.com>";
Mailbox yourInbox = Mailbox.get(new InternetAddress(recipient));
yourInbox.clear();

User assignee = User.get("assignee", true, Collections.emptyMap());
UserProperty p = new Mailer.UserProperty("assignee@test.com");
assignee.addProperty(p);
ClaimEmailer.sendEmailIfConfigured(assignee, "assignedByMe", "Test build", "test reason", "jobs/TestBuild/");

assertEquals(0,yourInbox.size());
}

/*
* Test that mail is sent to the assignee if mail sending is configured
*/
@Test
public void testSendEmailConfigured() throws Exception {

JenkinsLocationConfiguration.get().setAdminAddress("test <test@test.com>");
JenkinsLocationConfiguration.get().setUrl("localhost:8080/jenkins/");

ClaimConfig config = ClaimConfig.get();
config.setSendEmails(true);

String recipient = "assignee <assignee@test.com>";
Mailbox yourInbox = Mailbox.get(new InternetAddress(recipient));
yourInbox.clear();

User assignee = User.get("assignee", true, Collections.emptyMap());
UserProperty p = new Mailer.UserProperty("assignee@test.com");
assignee.addProperty(p);
ClaimEmailer.sendEmailIfConfigured(assignee, "assignedBy", "Test build", "test reason", "jobs/TestBuild/");

assertEquals(1,yourInbox.size());
Address[] senders = yourInbox.get(0).getFrom();
assertEquals(1,senders.length);
assertEquals("test <test@test.com>",senders[0].toString());

Object content = yourInbox.get(0).getContent();
assertTrue("Mail content should contain the reason",content.toString().contains(Messages.ClaimEmailer_Reason("test reason")));
assertTrue("Mail content should contain the details",content.toString().contains(Messages.ClaimEmailer_Details("localhost:8080/jenkins/jobs/TestBuild/")));
assertTrue("Mail content should assignment text",content.toString().contains(Messages.ClaimEmailer_Text("Test build", "assignedBy")));
}


}

0 comments on commit a042eaa

Please sign in to comment.