Skip to content

Commit

Permalink
Fixed JENKINS-13302
Browse files Browse the repository at this point in the history
Added option to save the output from the email in the workspace.
  • Loading branch information
slide committed Apr 19, 2013
1 parent 355af68 commit 7cabc47
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 84 deletions.
36 changes: 30 additions & 6 deletions src/main/java/hudson/plugins/emailext/ExtendedEmailPublisher.java
Expand Up @@ -31,6 +31,7 @@

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import hudson.FilePath;
import hudson.model.TaskListener;

import org.apache.commons.lang.StringUtils;
Expand All @@ -57,6 +58,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.logging.Level;
Expand Down Expand Up @@ -179,6 +181,11 @@ public static List<EmailTrigger> getTriggersForNonConfiguredInstance() {
* Reply-To value for the e-mail
*/
public String replyTo;

/**
* If true, save the generated email content to email-ext-message.[txt|html]
*/
public boolean saveOutput = false;

private MatrixTriggerMode matrixTriggerMode;

Expand Down Expand Up @@ -304,7 +311,7 @@ private boolean _perform(AbstractBuild<?, ?> build, BuildListener listener, bool

private boolean sendMail(EmailType mailType, AbstractBuild<?, ?> build, BuildListener listener, EmailTrigger trigger, Map<String, EmailTrigger> triggered) {
try {
MimeMessage msg = createMail(mailType, build, listener);
MimeMessage msg = createMail(mailType, build, listener, trigger);
debug(listener.getLogger(), "Successfully created MimeMessage");
Address[] allRecipients = msg.getAllRecipients();
int retries = 0;
Expand Down Expand Up @@ -438,7 +445,7 @@ private boolean executePresendScript(AbstractBuild<?, ?> build, BuildListener li
return !cancel;
}

private MimeMessage createMail(EmailType type, AbstractBuild<?, ?> build, BuildListener listener) throws MessagingException, IOException, InterruptedException {
private MimeMessage createMail(EmailType type, AbstractBuild<?, ?> build, BuildListener listener, EmailTrigger trigger) throws MessagingException, IOException, InterruptedException {
boolean overrideGlobalSettings = ExtendedEmailPublisher.DESCRIPTOR.getOverrideGlobalSettings();

MimeMessage msg;
Expand Down Expand Up @@ -473,8 +480,7 @@ private MimeMessage createMail(EmailType type, AbstractBuild<?, ?> build, BuildL
setSubject(type, build, msg, listener, charset);

Multipart multipart = new MimeMultipart();

multipart.addBodyPart(getContent(type, build, listener, charset));
multipart.addBodyPart(getContent(type, build, listener, charset, trigger));

AttachmentUtils attachments = new AttachmentUtils(attachmentsPattern);
attachments.attach(multipart, this, build, listener);
Expand Down Expand Up @@ -687,10 +693,10 @@ public boolean isExecuteOnMatrixNodes() {
|| MatrixTriggerMode.ONLY_CONFIGURATIONS == mtm;
}

private MimeBodyPart getContent(final EmailType type, final AbstractBuild<?, ?> build, BuildListener listener, String charset)
private MimeBodyPart getContent(final EmailType type, final AbstractBuild<?, ?> build, BuildListener listener, String charset, EmailTrigger trigger)
throws MessagingException {
final String text = new ContentBuilder().transformText(type.getBody(), this, build, listener);

String messageContentType = contentType;
// contentType is null if the project was not reconfigured after upgrading.
if (messageContentType == null || "default".equals(messageContentType)) {
Expand All @@ -702,6 +708,24 @@ private MimeBodyPart getContent(final EmailType type, final AbstractBuild<?, ?>
}
}
messageContentType += "; charset=" + charset;

try {
if(saveOutput) {
Random random = new Random();
String extension = ".html";
if(messageContentType.startsWith("text/plain")) {
extension = ".txt";
}

FilePath savedOutput = new FilePath(build.getWorkspace(),
String.format("%s-%s%d%s", trigger.getDescriptor().getTriggerName(), build.getId(), random.nextInt(), extension));
savedOutput.write(text, charset);
}
} catch(IOException e) {
listener.getLogger().println("Error trying to save email output to file. " + e.getMessage());
} catch(InterruptedException e) {
listener.getLogger().println("Error trying to save email output to file. " + e.getMessage());
}

// set the email message text
// (plain text or HTML depending on the content type)
Expand Down
Expand Up @@ -299,6 +299,7 @@ public Publisher newInstance(StaplerRequest req, JSONObject formData)
m.attachBuildLog = "true".equalsIgnoreCase(formData.optString("project_attach_buildlog"));
m.compressBuildLog = "true".equalsIgnoreCase(formData.optString("project_compress_buildlog"));
m.replyTo = formData.getString("project_replyto");
m.saveOutput = "true".equalsIgnoreCase(formData.optString("project_save_output"));
m.configuredTriggers = new ArrayList<EmailTrigger>();

// Create a new email trigger for each one that is configured
Expand Down
Expand Up @@ -10,6 +10,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import jenkins.model.Jenkins;
import net.java.sezpoz.Index;
import net.java.sezpoz.IndexItem;
import org.apache.commons.lang.StringUtils;
Expand Down Expand Up @@ -72,7 +73,8 @@ public String transformText(String origText, ExtendedEmailPublisher publisher, A

public static List<TokenMacro> getPrivateMacros() {
List<TokenMacro> macros = new ArrayList<TokenMacro>();
for (final IndexItem<EmailToken, TokenMacro> item : Index.load(EmailToken.class, TokenMacro.class)) {
ClassLoader cl = Jenkins.getInstance().pluginManager.uberClassLoader;
for (final IndexItem<EmailToken, TokenMacro> item : Index.load(EmailToken.class, TokenMacro.class, cl)) {
try {
macros.add(item.instance());
} catch (Exception e) {
Expand Down
Expand Up @@ -118,6 +118,13 @@ f.advanced() {
}
}
}
tr() {
td(colspan: "4") {
f.entry(title: _("Save Generated E-mail to Workspace"), help: "/plugin/email-ext/help/projectConfig/saveOutput.html") {
f.checkbox(name: "project_save_output", checked: instance?.saveOutput)
}
}
}
tr() {
td()
td(colspan: "3", style: "margin-left:10px") {
Expand Down
4 changes: 4 additions & 0 deletions src/main/webapp/help/projectConfig/saveOutput.html
@@ -0,0 +1,4 @@
<div>
Check this to enable saving the generated email content to a file in the
workspace. The file will be named "triggername-buildid.[txt|html].
</div>
145 changes: 68 additions & 77 deletions src/test/java/hudson/plugins/emailext/plugins/ContentBuilderTest.java
Expand Up @@ -15,112 +15,103 @@
import static org.mockito.Mockito.*;

public class ContentBuilderTest
extends HudsonTestCase
{
extends HudsonTestCase {

private ExtendedEmailPublisher publisher;
private StreamTaskListener listener;
private AbstractBuild<?, ?> build;

@Override
public void setUp()
throws Exception
{
throws Exception {
super.setUp();

listener = new StreamTaskListener(System.out);

publisher = mock(ExtendedEmailPublisher.class);
publisher.defaultContent = "For only 10 easy payment of $69.99 , AWESOME-O 4000 can be yours!";
publisher.defaultSubject = "How would you like your very own AWESOME-O 4000?";
publisher.recipientList = "ashlux@gmail.com";

Field f = ExtendedEmailPublisherDescriptor.class.getDeclaredField( "defaultBody" );
f.setAccessible( true );
f.set( ExtendedEmailPublisher.DESCRIPTOR, "Give me $4000 and I'll mail you a check for $40,000!" );
f = ExtendedEmailPublisherDescriptor.class.getDeclaredField( "defaultSubject" );
f.setAccessible( true );
f.set( ExtendedEmailPublisher.DESCRIPTOR, "Nigerian needs your help!" );

f = ExtendedEmailPublisherDescriptor.class.getDeclaredField( "recipientList" );
f.setAccessible( true );
f.set( ExtendedEmailPublisher.DESCRIPTOR, "ashlux@gmail.com" );
Field f = ExtendedEmailPublisherDescriptor.class.getDeclaredField("defaultBody");
f.setAccessible(true);
f.set(ExtendedEmailPublisher.DESCRIPTOR, "Give me $4000 and I'll mail you a check for $40,000!");
f = ExtendedEmailPublisherDescriptor.class.getDeclaredField("defaultSubject");
f.setAccessible(true);
f.set(ExtendedEmailPublisher.DESCRIPTOR, "Nigerian needs your help!");

f = ExtendedEmailPublisherDescriptor.class.getDeclaredField("recipientList");
f.setAccessible(true);
f.set(ExtendedEmailPublisher.DESCRIPTOR, "ashlux@gmail.com");

build = mock(AbstractBuild.class);
when(build.getEnvironment(listener)).thenReturn(new EnvVars());
}

public void testTransformText_shouldExpand_$PROJECT_DEFAULT_CONTENT()
throws IOException, InterruptedException
{
assertEquals(publisher.defaultContent, new ContentBuilder().transformText( "$PROJECT_DEFAULT_CONTENT", publisher,
build, listener ));
assertEquals(publisher.defaultContent, new ContentBuilder().transformText( "${PROJECT_DEFAULT_CONTENT}", publisher,
build, listener ));
throws IOException, InterruptedException {
assertEquals(publisher.defaultContent, new ContentBuilder().transformText("$PROJECT_DEFAULT_CONTENT", publisher,
build, listener));
assertEquals(publisher.defaultContent, new ContentBuilder().transformText("${PROJECT_DEFAULT_CONTENT}", publisher,
build, listener));
}

public void testTransformText_shouldExpand_$PROJECT_DEFAULT_SUBJECT()
throws IOException, InterruptedException
{
assertEquals(publisher.defaultSubject, new ContentBuilder().transformText( "$PROJECT_DEFAULT_SUBJECT", publisher,
build, listener ));
assertEquals(publisher.defaultSubject, new ContentBuilder().transformText( "${PROJECT_DEFAULT_SUBJECT}", publisher,
build, listener ));
throws IOException, InterruptedException {
assertEquals(publisher.defaultSubject, new ContentBuilder().transformText("$PROJECT_DEFAULT_SUBJECT", publisher,
build, listener));
assertEquals(publisher.defaultSubject, new ContentBuilder().transformText("${PROJECT_DEFAULT_SUBJECT}", publisher,
build, listener));
}



public void testTransformText_shouldExpand_$DEFAULT_CONTENT()
throws IOException, InterruptedException
{
assertEquals( ExtendedEmailPublisher.DESCRIPTOR.getDefaultBody(),
new ContentBuilder().transformText( "$DEFAULT_CONTENT", publisher,
build, listener ) );
assertEquals( ExtendedEmailPublisher.DESCRIPTOR.getDefaultBody(),
new ContentBuilder().transformText( "${DEFAULT_CONTENT}", publisher,
build, listener ) );
throws IOException, InterruptedException {
assertEquals(ExtendedEmailPublisher.DESCRIPTOR.getDefaultBody(),
new ContentBuilder().transformText("$DEFAULT_CONTENT", publisher,
build, listener));
assertEquals(ExtendedEmailPublisher.DESCRIPTOR.getDefaultBody(),
new ContentBuilder().transformText("${DEFAULT_CONTENT}", publisher,
build, listener));
}

public void testTransformText_shouldExpand_$DEFAULT_SUBJECT()
throws IOException, InterruptedException
{
assertEquals( ExtendedEmailPublisher.DESCRIPTOR.getDefaultSubject(),
new ContentBuilder().transformText( "$DEFAULT_SUBJECT", publisher,
build, listener ) );
assertEquals( ExtendedEmailPublisher.DESCRIPTOR.getDefaultSubject(),
new ContentBuilder().transformText( "${DEFAULT_SUBJECT}", publisher,
build, listener ) );
throws IOException, InterruptedException {
assertEquals(ExtendedEmailPublisher.DESCRIPTOR.getDefaultSubject(),
new ContentBuilder().transformText("$DEFAULT_SUBJECT", publisher,
build, listener));
assertEquals(ExtendedEmailPublisher.DESCRIPTOR.getDefaultSubject(),
new ContentBuilder().transformText("${DEFAULT_SUBJECT}", publisher,
build, listener));
}

public void testTransformText_shouldExpand_$DEFAULT_RECIPIENT_LIST()
throws IOException, InterruptedException
{
assertEquals( ExtendedEmailPublisher.DESCRIPTOR.getDefaultRecipients(),
new ContentBuilder().transformText( "$DEFAULT_RECIPIENTS", publisher,
build, listener ) );
assertEquals( ExtendedEmailPublisher.DESCRIPTOR.getDefaultRecipients(),
new ContentBuilder().transformText( "${DEFAULT_RECIPIENTS}", publisher,
build, listener ) );
throws IOException, InterruptedException {
assertEquals(ExtendedEmailPublisher.DESCRIPTOR.getDefaultRecipients(),
new ContentBuilder().transformText("$DEFAULT_RECIPIENTS", publisher,
build, listener));
assertEquals(ExtendedEmailPublisher.DESCRIPTOR.getDefaultRecipients(),
new ContentBuilder().transformText("${DEFAULT_RECIPIENTS}", publisher,
build, listener));
}

public void testTransformText_shouldExpand_$DEFAULT_PRESEND_SCRIPT()
throws IOException, InterruptedException
{
assertEquals( ExtendedEmailPublisher.DESCRIPTOR.getDefaultPresendScript(),
new ContentBuilder().transformText( "$DEFAULT_PRESEND_SCRIPT", publisher,
build, listener ) );
assertEquals( ExtendedEmailPublisher.DESCRIPTOR.getDefaultPresendScript(),
new ContentBuilder().transformText( "${DEFAULT_PRESEND_SCRIPT}", publisher,
build, listener ) );
}

public void testTransformText_noNPEWithNullDefaultSubjectBody() throws NoSuchFieldException, IllegalAccessException
{
Field f = ExtendedEmailPublisherDescriptor.class.getDeclaredField( "defaultBody" );
f.setAccessible( true );
f.set( ExtendedEmailPublisher.DESCRIPTOR, null );
f = ExtendedEmailPublisherDescriptor.class.getDeclaredField( "defaultSubject" );
f.setAccessible( true );
f.set( ExtendedEmailPublisher.DESCRIPTOR, null );
assertEquals( "", new ContentBuilder().transformText( "$DEFAULT_SUBJECT", publisher, build, listener));
assertEquals( "", new ContentBuilder().transformText( "$DEFAULT_CONTENT", publisher, build, listener));
throws IOException, InterruptedException {
assertEquals(ExtendedEmailPublisher.DESCRIPTOR.getDefaultPresendScript(),
new ContentBuilder().transformText("$DEFAULT_PRESEND_SCRIPT", publisher,
build, listener));
assertEquals(ExtendedEmailPublisher.DESCRIPTOR.getDefaultPresendScript(),
new ContentBuilder().transformText("${DEFAULT_PRESEND_SCRIPT}", publisher,
build, listener));
}

public void testTransformText_noNPEWithNullDefaultSubjectBody() throws NoSuchFieldException, IllegalAccessException {
Field f = ExtendedEmailPublisherDescriptor.class.getDeclaredField("defaultBody");
f.setAccessible(true);
f.set(ExtendedEmailPublisher.DESCRIPTOR, null);
f = ExtendedEmailPublisherDescriptor.class.getDeclaredField("defaultSubject");
f.setAccessible(true);
f.set(ExtendedEmailPublisher.DESCRIPTOR, null);
assertEquals("", new ContentBuilder().transformText("$DEFAULT_SUBJECT", publisher, build, listener));
assertEquals("", new ContentBuilder().transformText("$DEFAULT_CONTENT", publisher, build, listener));
}
}

0 comments on commit 7cabc47

Please sign in to comment.