Skip to content

Commit

Permalink
Fix JENKINS-12421
Browse files Browse the repository at this point in the history
Implement pre-send script that allows modifying or cancelling the
sending of the email.
  • Loading branch information
slide committed May 21, 2012
1 parent 67c90c3 commit 5fa24b4
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 40 deletions.
57 changes: 54 additions & 3 deletions src/main/java/hudson/plugins/emailext/ExtendedEmailPublisher.java
Expand Up @@ -26,9 +26,18 @@
import hudson.tasks.Publisher;
import hudson.tasks.Mailer;

import jenkins.model.Jenkins;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;

import org.apache.commons.lang.StringUtils;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.ImportCustomizer;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
Expand Down Expand Up @@ -139,6 +148,11 @@ public static List<EmailTrigger> getTriggersForNonConfiguredInstance() {
* The project wide set of attachments.
*/
public String attachmentsPattern;

/**
* The project's pre-send script.
*/
public String presendScript;

private MatrixTriggerMode matrixTriggerMode;

Expand Down Expand Up @@ -264,9 +278,14 @@ private boolean sendMail(EmailType mailType, AbstractBuild<?, ?> build, BuildLis
buf.append(' ').append(a);
}
listener.getLogger().println(buf);
Transport.send(msg);
if (build.getAction(MailMessageIdAction.class) == null) {
build.addAction(new MailMessageIdAction(msg.getMessageID()));
if(executePresendScript(build, listener, msg)) {
Transport.send(msg);
if (build.getAction(MailMessageIdAction.class) == null) {
build.addAction(new MailMessageIdAction(msg.getMessageID()));
}
} else {
listener.getLogger().println("Email sending was cancelled"
+ " by user script.");
}
return true;
} else {
Expand All @@ -280,6 +299,38 @@ private boolean sendMail(EmailType mailType, AbstractBuild<?, ?> build, BuildLis

return false;
}

private boolean executePresendScript(AbstractBuild<?, ?> build, BuildListener listener, MimeMessage msg)
throws RuntimeException {
boolean cancel = false;
if(StringUtils.isNotBlank(presendScript)) {
CompilerConfiguration cc = new CompilerConfiguration();
cc.addCompilationCustomizers(new ImportCustomizer().addStarImports(
"jenkins",
"jenkins.model",
"hudson",
"hudson.model"));
ClassLoader cl = Jenkins.getInstance().getPluginManager().uberClassLoader;
GroovyShell shell = new GroovyShell(cl,new Binding(),cc);
StringWriter out = new StringWriter();
PrintWriter pw = new PrintWriter(out);
shell.setVariable("build", build);
shell.setVariable("msg", msg);
shell.setVariable("logger", listener.getLogger());
shell.setVariable("cancel", cancel);
try {
Object output = shell.evaluate(presendScript);
if(output!=null) {
pw.println("Result: "+output);
cancel = ((Boolean)shell.getVariable("cancel")).booleanValue();
}
} catch (Throwable t) {
t.printStackTrace(pw);
listener.getLogger().println(out.toString());
}
}
return !cancel;
}

private MimeMessage createMail(EmailType type, AbstractBuild<?, ?> build, BuildListener listener) throws MessagingException, IOException, InterruptedException {
boolean overrideGlobalSettings = ExtendedEmailPublisher.DESCRIPTOR.getOverrideGlobalSettings();
Expand Down
Expand Up @@ -257,6 +257,7 @@ public Publisher newInstance(StaplerRequest req, JSONObject formData)
m.defaultSubject = formData.getString("project_default_subject");
m.defaultContent = formData.getString("project_default_content");
m.attachmentsPattern = formData.getString("project_attachments");
m.presendScript = formData.getString("project_presend_script");
m.configuredTriggers = new ArrayList<EmailTrigger>();

// Create a new email trigger for each one that is configured
Expand Down
Expand Up @@ -4,7 +4,7 @@
xmlns:m="/hudson/plugins/emailext/tags">
<!--
This script defines the view for the extended email plugin.
-->
-->

<!-- In case form is repeated, uniquify ids with a prefix -->
<j:set var="secId" value="emailext-${h.generateId()}-"/>
Expand Down Expand Up @@ -83,7 +83,7 @@
</j:choose>
</f:entry>

<!-- This is the default attachments set for the projcet. -->
<!-- This is the default attachments set for the project. -->
<f:entry title="${%Attachments}"
help="/plugin/email-ext/help/projectConfig/attachments.html"
description="${%description('http://ant.apache.org/manual/Types/fileset.html')}">
Expand All @@ -99,6 +99,8 @@
</j:choose>
</f:entry>



<!-- This is the help section. It displays a bunch of dynamic help for all content tokens. -->
<tr>
<td></td>
Expand All @@ -125,7 +127,19 @@
whether or not to send email to developers who made changes, and whether or
not to send email to the global list of devs-->
<f:advanced>

<tr>
<td colspan="4">
<!-- This is the pre-send script area -->
<f:entry title="${%Pre-send Script}"
help="/plugin/email-ext/help/projectConfig/presendScript.html">
<f:textarea
class="setting-input"
name="project_presend_script"
id="project_presend_script"
value="${instance.presendScript}"/>
</f:entry>
</td>
</tr>
<tr>
<td></td>
<td colspan="3" style="margin-left:10px">
Expand Down Expand Up @@ -265,5 +279,5 @@
if (!window.emailExtInit['${secId}']) addTrigger('Failure','${secId}');
window.emailExtInit['${secId}'] = 1;
</script>
</j:if>
</j:if>
</j:jelly>
9 changes: 9 additions & 0 deletions src/main/webapp/help/projectConfig/presendScript.html
@@ -0,0 +1,9 @@
<div>
This script will be run prior to sending the email to allow
modifying the email before sending. The MimeMessage variable
is "msg," the build is also available as "build" and a logger
is available as "logger."
<br/><br/>
You may also cancel sending the email by setting the boolean
variable "cancel" to true.
</div>
Expand Up @@ -53,6 +53,7 @@ public void setUp()
publisher.defaultContent = "%DEFAULT_CONTENT";
publisher.attachmentsPattern = "";
publisher.recipientList = "%DEFAULT_RECIPIENTS";
publisher.presendScript = "";

project = createFreeStyleProject();
project.getPublishersList().add( publisher );
Expand Down Expand Up @@ -344,39 +345,70 @@ public void testShouldSendEmailUsingUtf8ByDefault()
}
}

// public void testsSendToRequester()
// throws Exception
// {
// SuccessTrigger successTrigger = new SuccessTrigger();
// successTrigger.setEmail(new EmailType(){{
// setSendToRequester(true);
// }});
// publisher.getConfiguredTriggers().add( successTrigger );
//
// User u = User.get("ssogabe");
// Mailer.UserProperty prop = new Mailer.UserProperty("ssogabe@xxx.com");
// u.addProperty(prop);
//
// UserIdCause cause = new MockUserIdCause("ssogabe");
//
// FreeStyleBuild build = project.scheduleBuild2( 0, cause ).get();
// assertBuildStatusSuccess( build );
//
// assertEquals( 1, Mailbox.get( "ssogabe@xxx.com" ).size() );
// }
//
// private static class MockUserIdCause extends UserIdCause {
// private String userId;
//
// public MockUserIdCause(String userId) {
// this.userId = userId;
// }
//
// @Override
// public String getUserId() {
// return userId;
// }
// }
public void testCancelFromPresendScriptCausesNoEmail() throws Exception {
publisher.presendScript = "cancel = true";
SuccessTrigger successTrigger = new SuccessTrigger();
successTrigger.setEmail(new EmailType(){{
setSendToRequester(true);
}});
publisher.getConfiguredTriggers().add( successTrigger );

User u = User.get("kutzi");
u.setFullName("Christoph Kutzinski");
Mailer.UserProperty prop = new Mailer.UserProperty("kutzi@xxx.com");
u.addProperty(prop);

UserCause cause = new MockUserCause("kutzi");

FreeStyleBuild build = project.scheduleBuild2( 0, cause ).get();
assertBuildStatusSuccess( build );

assertEquals( 0, Mailbox.get( "kutzi@xxx.com" ).size() );
}

public void testNoCancelFromPresendScriptCausesEmail() throws Exception {
publisher.presendScript = "def hello = 'world'\n";
SuccessTrigger successTrigger = new SuccessTrigger();
successTrigger.setEmail(new EmailType(){{
setSendToRequester(true);
}});
publisher.getConfiguredTriggers().add( successTrigger );

User u = User.get("kutzi");
u.setFullName("Christoph Kutzinski");
Mailer.UserProperty prop = new Mailer.UserProperty("kutzi@xxx.com");
u.addProperty(prop);

UserCause cause = new MockUserCause("kutzi");

FreeStyleBuild build = project.scheduleBuild2( 0, cause ).get();
assertBuildStatusSuccess( build );

assertEquals( 1, Mailbox.get( "kutzi@xxx.com" ).size() );
}

public void testPresendScriptModifiesTo() throws Exception {
publisher.presendScript = "import javax.mail.Message.RecipientType\n"
+ "msg.setRecipients(RecipientType.TO, 'slide.o.mix@xxx.com')";
SuccessTrigger successTrigger = new SuccessTrigger();
successTrigger.setEmail(new EmailType(){{
setSendToRequester(true);
}});
publisher.getConfiguredTriggers().add( successTrigger );

User u = User.get("kutzi");
u.setFullName("Christoph Kutzinski");
Mailer.UserProperty prop = new Mailer.UserProperty("kutzi@xxx.com");
u.addProperty(prop);

UserCause cause = new MockUserCause("kutzi");

FreeStyleBuild build = project.scheduleBuild2( 0, cause ).get();
assertBuildStatusSuccess( build );

assertEquals( 0, Mailbox.get( "kutzi@xxx.com" ).size() );
assertEquals( 1, Mailbox.get( "slide.o.mix@xxx.com" ).size() );
}

public void testSendToRequesterLegacy() throws Exception {
SuccessTrigger successTrigger = new SuccessTrigger();
Expand Down

0 comments on commit 5fa24b4

Please sign in to comment.