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.
package ru.tovbin.ivan.builders
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()}")
attachBody.setFileName(fileName)
log.debug("Body filename: ${attachBody.getFileName()}")
return attachBody
}
public class Builder {
private Builder() {}
private Builder createEmail(Email email){
EmailBuilder.this.email = email
return this
}
public Builder setFromName(String fromName){
log.debug("setFromName. value: {}", fromName)
EmailBuilder.this.email.setFromName(fromName)
return this
}
public Builder setFrom(String from){
log.debug("setFrom. value: {}", from)
EmailBuilder.this.email.setFrom(from)
return this
}
public Builder setTo(String to){
log.debug("setTo. value: {}", to)
EmailBuilder.this.email.setTo(to)
return this
}
public Builder setCc(String cc){
log.debug("setCc. value: {}", cc)
EmailBuilder.this.email.setCc(cc)
return this
}
public Builder setSubject(String subject){
log.debug("setSubject. value: {}", subject)
EmailBuilder.this.email.setSubject(subject)
return this
}
public Builder setBody(String body){
log.debug("setBody. value: {}", body)
EmailBuilder.this.email.setBody(body)
return this
}
public Builder setMimeType(String mimeType){
log.debug("setMimeType. value: {}", mimeType)
EmailBuilder.this.email.setMimeType(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()))
}
EmailBuilder.this.email.setMultipart(multipart)
return this
}
public EmailBuilder send() {
SMTPMailServer mailServer = ComponentAccessor.getMailServerManager().getDefaultSMTPMailServer()
Thread.currentThread().setContextClassLoader(javax.mail.Message.class.getClassLoader())
log.debug(EmailBuilder.this.email.toString())
mailServer.send(EmailBuilder.this.email)
return EmailBuilder.this;
}
}
}
And here's how you use it in your scripts:
import ru.tovbin.ivan.builders.EmailBuilder
EmailBuilder.create("destination@email.com")
.setFromName("some name")
.setFrom("from@email.com")
.setCc("copy@email.com")
.setSubject("some subject")
.setBody("some body")
.setMimeType("text/html")
.addAttachments(issue.getAttachments())
.send()
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!
Ivan Tovbin
9 comments