Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
Community Members
Community Events
Community Groups

Email Builder - An easy way to create custom emails for your groovy scripts

Hello everyone!

In my first (and hopefully not the last) article here on The Community I'd like to share an easy way to construct and send custom emails from your Groovy scripts. Please keep in mind that Scriptrunner add-on is required for this. 

While browsing the various questions here on The Community I've noticed that alot of people are asking how to send a custom email from their scripts. Now we do know that Scriptrunner has a great built-in script for sending custom emails, and most of the time it works fine. Unfortunatly however you can't really use it from within your other scripts, which is especially the case if you store most of your scripts on file system. Nor does it allow you to set various parts of your email conditionally (like subject, body, attachments, recipients, etc).

With that in mind I've developed this rather simple class which allows you once imported into your other scripts to easily construct and send custom email. We've already had a similar builder for creating and updating issues, developed by my colleague and fellow champion @Mark Markov so I figured this logic could be used for emails as well. 


import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.attachment.Attachment
import com.atlassian.jira.util.PathUtils
import com.atlassian.mail.Email
import com.atlassian.mail.server.SMTPMailServer
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import javax.activation.DataHandler
import javax.activation.FileDataSource
import javax.mail.BodyPart
import javax.mail.Multipart
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMultipart
import com.atlassian.jira.issue.Issue

class EmailBuilder {

private static Logger log = LoggerFactory.getLogger(this.class.getName())
private Email email
private EmailBuilder(){}

public static Builder create(String to){
return new EmailBuilder.Builder(new EmailBuilder()).createEmail(new Email(to))

private static File getFilePath(Attachment attachment){
log.debug("Getting path for attachment ${attachment.getFilename()} from issue ${attachment.getIssue().getKey()}...")
int u = Integer.parseInt(attachment.getIssue().getKey().split("-")[1])
int kk = (int)Math.ceil(u/10000)*10000
String path = PathUtils.joinPaths(ComponentAccessor.getAttachmentPathManager().getAttachmentPath(), attachment.getIssue().getProjectObject().getKey(), kk.toString() ,attachment.getIssue().getKey(), attachment.getId().toString())
log.debug("File path for ${attachment.getFilename()}: ${path}")
File filePath = new File(path)
return filePath

private static BodyPart getAttachBody(File filePath, String fileName){
log.debug("Building body for file ${fileName} at path ${filePath.toString()}....")
BodyPart attachBody = new MimeBodyPart()
attachBody.setDataHandler(new DataHandler(new FileDataSource(filePath)))
log.debug("Body data handler name:${attachBody.getDataHandler().getName()}")
log.debug("Body filename: ${attachBody.getFileName()}")
return attachBody


public class Builder {
private Builder() {}

private Builder createEmail(Email email){ = email
return this

public Builder setFromName(String fromName){
log.debug("setFromName. value: {}", fromName)
return this

public Builder setFrom(String from){
log.debug("setFrom. value: {}", from)
return this

public Builder setTo(String to){
log.debug("setTo. value: {}", to)
return this

public Builder setCc(String cc){
log.debug("setCc. value: {}", cc)
return this

public Builder setSubject(String subject){
log.debug("setSubject. value: {}", subject)
return this

public Builder setBody(String body){
log.debug("setBody. value: {}", body)
return this

public Builder setMimeType(String mimeType){
log.debug("setMimeType. value: {}", mimeType)
return this

public Builder addAttachments(List<Attachment> attachmentList){
log.debug("Attachments to add: ${attachmentList.toString()}")
Multipart multipart = new MimeMultipart()
for (int i = 0; i < attachmentList.size(); i++){
multipart.addBodyPart(EmailBuilder.getAttachBody(EmailBuilder.getFilePath(attachmentList[i]), attachmentList[i].getFilename()))
return this

public EmailBuilder send() {
SMTPMailServer mailServer = ComponentAccessor.getMailServerManager().getDefaultSMTPMailServer()
return EmailBuilder.this;


And here's how you use it in your scripts:


.setFromName("some name")
.setSubject("some subject")
.setBody("some body")

Pretty easy, huh?

Well that's about it, I hope this will be helpful. Please feel free to share your thoughts and questions. Any feedback is always welcome!




Thanks for your article. 

Do you have experience with generating email in different formats like RTF, HTML ? 

And of course, how do you handling styles, footer and some scripts? Also, it will be so interesting how it represent in Office365, G-Suite, Yahoo and Zimbra. 





Gonchik Tsymzhitov

@Gonchik Tsymzhitov

We pass "text/html" to setMimeType() method and simply use HTML tags in email body, like so:

setBody("<font face=\"Calibri\" size=\"3\" color=\"black\"><b>some text:</b> <a href=\"$baseUrl/browse/$key\">ABC-123</a>some text<br><br><b>some text</b> some more text<br><b>some more text</b> some text<br><b>some tesxt</b></font>"

@Ivan Tovbin Thanks for your awesome clarify. 

BTW, have you check it on related platrforms? Or what kind of mail service or server do you using?

@Gonchik Tsymzhitov

We've been usuing IMB Notes 9 so far, but are looking at MS Exchange right now. Didn't really have any problems with either.

Thanks for opening my eyes about  IBM Notes 9 :)

@Ivan Tovbin How can you here generate valid urls to jira tickets and other objects from java-objects in code? :)


For example - you need to mention $issue and username. How can I do it with this class? 

@Evgeniy Buturlia

I suppose something like this should do the trick:

import com.atlassian.jira.component.ComponentAccessor

String baseurl = ComponentAccessor.getApplicationProperties().getString("jira.baseurl")
String issueUrl = "${baseurl}/browse/${issue.getKey()}"

Useful, thanks

Finally I've found The Best Script to email attachments!

I've spent hours googling for it, I believed all that time that it must be exist :)

I'll use it in my Listener later, but now I'm so happy and wanna thank you for it!

More over I want to share some useful changes I made:

PathUtils.joinPaths(ComponentAccessor.getAttachmentPathManager().getAttachmentPath(), attachment.getIssue().getProjectObject().getKey(), kk.toString() ,attachment.getIssue().getKey(), attachment.getId().toString())

it would be better to use here getOriginalKey() - I have a project, which was renamed, but it's folder named is still the named with it's original name...


And one more. The kk variable had a bad value in my Jira instance. So, I've found and read here info about "grouping numbers" which lead to next change:

int kk = (int) Math.round(Math.floor((double) / 10000)) * 10000

  As you can see, now kk doesn't depends on Issue number.

И ещё раз Спасибо! :)


Log in or Sign up to comment