24

I recently converted to Jenkins 2.x and I am experimenting with pipeline flow, but I can't seem to get the email-ext plugin to work with groovy script templates. Although my standard flow still work fine, if I try the following I get an error with unexpected token SCRIPT

    emailext mimeType: 'text/html', replyTo: 'xxxx', subject: "${env.JOB_NAME} - Build# ${env.BUILD_NUMBER} - ${env.BUILD_STATUS}", to: 'xxxx', body: "${SCRIPT, template='regressionfailed.groovy'}"

I know that there were issues with token expansion early on, but it seems like from the latest wiki updates those have been fixed. I also still get no token expansion for any tokens. Is there any good reference to get this working again. I would like to switch to the pipeline flow but the email template with token expansion is key to may work flow.

naven87
  • 964
  • 1
  • 7
  • 24

5 Answers5

24

There is no problem using emailext in declarative pipeline. But your script won't be able to access "build.result" parameter correctly because it is not yet finished. Like in the default script groovy-html.template.

Edit: Actually you can access build.result if you manually set it yourself.

So it is best to add a stage in the end of the declarative pipeline like so:

stage('Send email') {
    def mailRecipients = "your_recipients@company.com"
    def jobName = currentBuild.fullDisplayName

    emailext body: '''${SCRIPT, template="groovy-html.template"}''',
        mimeType: 'text/html',
        subject: "[Jenkins] ${jobName}",
        to: "${mailRecipients}",
        replyTo: "${mailRecipients}",
        recipientProviders: [[$class: 'CulpritsRecipientProvider']]
}

Also note, that if you are using your own script you cannot name it "groovy-html.template" or " groovy-text.template" because they are default of emailext (so the file will not even be accessed). See "Script content" here.

user3360767
  • 868
  • 7
  • 18
  • I rewrote to match above but the basic default groovy-html.template is still throwing errors, complaining about "Exception raised during template rendering: No such property: changeSet for class: org.jenkinsci.plugins.workflow.job.WorkflowRun " – naven87 Aug 15 '17 at 17:35
  • 1
    Yes. That is because of additional problem. Because the API changed, the function is now called changeSets, but the default template is not updated and still call the the old function. You will need to download the default template, change the call to changeSets and add iteration. Maybe it deserve a new question. – user3360767 Aug 16 '17 at 05:37
  • @user3360767 I fixed those bugs and the new release have working templates. – sorin Sep 20 '17 at 22:03
  • Where is the template file stored? How can I add mine? – Alex Pi Nov 16 '17 at 21:58
  • groovy-html.template file location please? – user4948798 May 09 '19 at 09:19
  • can anyone point me how do I use conditional statement like if () in this template correectly. I am comparing just an enviroment variable boolean value here but it seems this if statement I used is not working. ```if ( "${env.MY_ENV}" == "true" ) { %> blah blah <% }``` – vgdub Jun 03 '21 at 14:16
  • i keep seeing this 'grrooovy-html.template', but how do i reference an email template i created using the email template plugin? – mike01010 May 22 '23 at 19:14
10

Apparently everybody know it. There are 2 way to define a pipeline: declarative pipeline (start with 'pipeline') and scripted pipeline (start with 'node')

Using declarative pipeline, it must be specified the script to execute a procedure, i.e. use def to define variables. So in pipeline case:

stage('Email') {
    steps {
        script {
            def mailRecipients = 'XXX@xxxxx.xxx-domain'
            def jobName = currentBuild.fullDisplayName
            emailext body: '''${SCRIPT, template="groovy-html.template"}''',
            mimeType: 'text/html',
            subject: "[Jenkins] ${jobName}",
            to: "${mailRecipients}",
            replyTo: "${mailRecipients}",
            recipientProviders: [[$class: 'CulpritsRecipientProvider']]
        }
    }
}

I spent some time for this, I hope it is helpfull for someone else.

Daniele Cruciani
  • 623
  • 1
  • 8
  • 15
6

Faced the same issue today, apparently having the body defined before the emailext seem to do the trick:

def emailBody = '${SCRIPT, template="regressionfailed.groovy"}'
def emailSubject = "${env.JOB_NAME} - Build# ${env.BUILD_NUMBER} - ${env.BUILD_STATUS}"
emailext(mimeType: 'text/html', replyTo: 'xxxx', subject: emailSubject, to: 'xxxx', body: emailBody)

Remember you might still need to redo parts of your template.

Martin
  • 2,606
  • 4
  • 24
  • 38
  • Has anyone ported over some sample templates, it seems like the ones with the plug-in no longer work. – naven87 Apr 24 '17 at 20:21
  • @naven87 it depends on your template. You still have the same variables injected with pipelines as with freestyle jobs. If you have a matrix template for example, it will of course be incompatible with pipeline. I ended up having to write my own logic for setting up and rendering the template as I also needed some extra variables that was not available by default in the template. – Martin Apr 26 '17 at 08:17
  • When do as you suggest: def TEST = '${CHANGES, showPaths=true, format="%a: %r %p \n--\"%m\"", pathFormat="\n\t- %p"}' Then TEST return the text as it was written and it is not expanded to what we really want. – Doron Shai May 23 '17 at 12:42
4

I am surprised that nobody pointed out the fundamental issue with the error reported by OP. The error is coming from the Groovy compiler itself and it is coming because ${SCRIPT...} appeared inside double-quotes making it a GString (an invalid one). To fix the error mentioned in OP, you just have to use single-quotes instead:

    emailext mimeType: 'text/html', replyTo: 'xxxx', subject: "${env.JOB_NAME} - Build# ${env.BUILD_NUMBER} - ${env.BUILD_STATUS}", to: 'xxxx', body: '${SCRIPT, template='regressionfailed.groovy'}'

You can reproduce the error even using the standalone Groovy interpreter like this:

$ cat << 'END' > /tmp/t.groovy
> def emailext(Map opts) {
> }
>
> emailext mimeType: 'text/html', replyTo: 'xxxx', subject: "${env.JOB_NAME} - Build# ${env.BUILD_NUMBER} - ${env.BUILD_STATUS}", to: 'xxxx', body: "${SCRIPT, template='regressionfailed.groovy'}"
> END
$ groovy /tmp/t.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/private/tmp/t.groovy: 4: unexpected token: SCRIPT @ line 4, column 150.
   TATUS}", to: 'xxxx', body: "${SCRIPT, te
                                 ^

1 error
haridsv
  • 9,065
  • 4
  • 62
  • 65
  • 3 years later, but this solved my exact issue. I cannot stress enough how this simple solution is the right answer - many other answers here misleading or unnecessarily complex. – TVOHM Feb 03 '23 at 16:35
  • This solved the issue. – vince Jun 23 '23 at 08:28
-4

Email notification for Scripted pipeline:

mail bcc: '', body: body, cc: '', from: '', replyTo: '', subject: 'Build Done', to: 'xyzh@abc.com'
user2030113
  • 475
  • 1
  • 5
  • 14
  • you can delete the answer to regain lost rep... plus, the auto-gen username can be changed here: https://stackoverflow.com/users/edit/2030113 ;) – mirekphd Dec 07 '19 at 20:46