이 문서는 Jira Script Runner 활용하여 HTML 메일 보내기 가이드를 공유하기 위해 작성되었다.
| 도구명 | Jira, Script Runner |
|---|---|
| 비고 |
메일 서버 설정이 되어있어야 메일 보내기가 가능
Worflow Action 시 HTML 메일 보내기
메일 템플릿 만들기
- https://wordtohtml.net/ 접속 후 원하는 형식의 메일 템플릿을 작성 후 HTML Editor 부분을 따로 저장한다.
- 변수를 사용하려면 해당 변수자리에
${변수명}을 넣는다.
Script Runner Workflow Action 만들기
- 시스템 → 앱 관리 → Script Runner → Workflow → Create Workflow functions 선택
- 해당하는 Workflow와 Transition 선택 후 Validator 선택 후 Create
- Custom script validator 선택
Script 내용
Html 전체 글자수가 65535 이하인 경우
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.mail.Email
import com.atlassian.jira.mail.settings.MailSettings
import com.atlassian.mail.MailException
import com.atlassian.mail.server.SMTPMailServer
import com.atlassian.plugin.util.ContextClassLoaderSwitchingUtil
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.opensymphony.workflow.InvalidInputException
def issueManager = ComponentAccessor.getIssueManager()
// 이슈 Summary
def summaryfield = issue.getSummary()
// 그외 사용 할 변수 들
def variable1 = "칼럼1 변수"
def variable2 = "행1 변수"
def variable3 = "행2 변수"
def variable4 = "행3 변수"
// HTML 복사한 값 넣기
def body = """
<p style="text-align: center;"><strong>메일 템플릿</strong></p>
<p style="text-align: center;"><br></p>
<table style="width: 86%; margin: 0px auto; font-family: Calibri, sans-serif; border-collapse: collapse; border: 2px solid rgb(0, 0, 0);">
<tbody>
<tr>
<td style="width: 8.0675%; text-align: center; border: 2px solid rgb(0, 0, 0); background-color: rgb(239, 239, 239);">칼럼1</td>
<td style="width: 13.7802%; text-align: center; border: 2px solid rgb(0, 0, 0); background-color: rgb(239, 239, 239);">칼럼2</td>
<td style="width: 35.5014%; text-align: center; border: 2px solid rgb(0, 0, 0); background-color: rgb(239, 239, 239);">
<div style="text-align: center;">칼럼3</div>
</td>
<td style="width: 39.2953%; text-align: center; border: 2px solid rgb(0, 0, 0); background-color: rgb(239, 239, 239);">
<div style="text-align: center;">칼럼4</div>
</td>
</tr>
<tr>
<td rowspan="3" style="width: 8.042%; text-align: center; border: 2px solid rgb(0, 0, 0);">${variable1}</td>
<td style="width: 13.7802%; text-align: center; border: 2px solid rgb(0, 0, 0);">행1</td>
<td style="width: 35.5014%; text-align: center; border: 2px solid rgb(0, 0, 0);">${variable2}</td>
<td style="width: 39.2953%; text-align: center; border: 2px solid rgb(0, 0, 0);"><br></td>
</tr>
<tr>
<td style="width: 13.7802%; text-align: center; border: 2px solid rgb(0, 0, 0);">행2</td>
<td style="width: 35.5014%; text-align: center; border: 2px solid rgb(0, 0, 0);">${variable3}</td>
<td style="width: 39.2953%; text-align: center; border: 2px solid rgb(0, 0, 0);"><br></td>
</tr>
<tr>
<td style="width: 13.7802%; text-align: center; border: 2px solid rgb(0, 0, 0);">행3</td>
<td style="width: 35.5014%; text-align: center; border: 2px solid rgb(0, 0, 0);">${variable4}</td>
<td style="width: 39.2953%; text-align: center; border: 2px solid rgb(0, 0, 0);"><br></td>
</tr>
</tbody>
</table>
<p><br></p> """
//메일 받는 사람 설정(현재는 해당 이슈 담당자로 설정)
def userManager = ComponentAccessor.getUserManager()
def user = issue.getAssignee()
//기본 메일 주소 설정, 담당자 없을 시 보고자로 설정
if(user == null) {
user = issue.getReporter()
}
def receiver = user.getEmailAddress()
// 메일주소, 메일 제목, 내용
sendEmail(receiver.toString(), summary ,body)
// 메일보내기 함수
String sendEmail(String emailAddr, String subject, String body) {
def logger = Logger.getLogger(getClass())
logger.setLevel(Level.DEBUG)
// Stop emails being sent if the outgoing mail server gets disabled (useful if you start a script sending emails and need to stop it)
def mailSettings = ComponentAccessor.getComponent(MailSettings)
if (mailSettings?.send()?.disabled) {
logger.debug("메일 서버가 비활성 상태입니다.")
throw new InvalidInputException("메일 서버가 비활성 상태입니다.")
}
def mailServer = ComponentAccessor.mailServerManager.defaultSMTPMailServer
if (!mailServer) {
logger.debug("메일 서버가 설정되지 않았습니다.")
throw new InvalidInputException("메일 서버가 설정되지 않았습니다.")
}
def email = new Email(emailAddr)
email.setMimeType('text/html')
email.setSubject(subject)
email.setBody(body)
try {
// This is needed to avoid the exception about IMAPProvider
ContextClassLoaderSwitchingUtil.runInContext(SMTPMailServer.classLoader) {
mailServer.send(email)
}
logger.debug('Mail sent')
} catch (MailException e) {
logger.debug("Send mail failed with error: ${e.message}")
throw new InvalidInputException("메일 보내기에 실패했습니다.")
}
}
Html 전체 글자수가 65535 이상인 경우
- HTML 내용이 큰 경우 위의 방법으로 진행 시 에러가 발생
- 방법 1: 에러를 방지하기 위해 해당 HTML을 파일로 저장 후 사용 - 파일에서 읽을 때 변수가 치환되지 않아
replace를 사용하여 변수를 치환
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.mail.Email
import com.atlassian.jira.mail.settings.MailSettings
import com.atlassian.mail.MailException
import com.atlassian.mail.server.SMTPMailServer
import com.atlassian.plugin.util.ContextClassLoaderSwitchingUtil
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.opensymphony.workflow.InvalidInputException
def issueManager = ComponentAccessor.getIssueManager()
// 이슈 Summary
def summaryfield = issue.getSummary()
// 그외 사용 할 변수 들
def variable1 = "칼럼1 변수"
def variable2 = "행1 변수"
def variable3 = "행2 변수"
def variable4 = "행3 변수"
// HTML 저장한 파일 경로 입력
def body = new File('/atlassian/application-data/jira-home/scripts/jktest.groovy').text
// 해당 변수들 replace로 변환
body = body.replace('${variable1}', "칼럼1 변수")
body = body.replace('${variable2}', "행1 변수")
body = body.replace('${variable3}', "행2 변수")
body = body.replace('${variable4}', "행3 변수")
//메일 받는 사람 설정(현재는 해당 이슈 담당자로 설정)
def userManager = ComponentAccessor.getUserManager()
def user = issue.getAssignee()
//기본 메일 주소 설정, 담당자 없을 시 보고자로 설정
if(user == null) {
user = issue.getReporter()
}
def receiver = user.getEmailAddress()
// 메일주소, 메일 제목, 내용
sendEmail(receiver.toString(), summary ,body)
// 메일보내기 함수
String sendEmail(String emailAddr, String subject, String body) {
def logger = Logger.getLogger(getClass())
logger.setLevel(Level.DEBUG)
// Stop emails being sent if the outgoing mail server gets disabled (useful if you start a script sending emails and need to stop it)
def mailSettings = ComponentAccessor.getComponent(MailSettings)
if (mailSettings?.send()?.disabled) {
logger.debug("메일 서버가 비활성 상태입니다.")
throw new InvalidInputException("메일 서버가 비활성 상태입니다.")
}
def mailServer = ComponentAccessor.mailServerManager.defaultSMTPMailServer
if (!mailServer) {
logger.debug("메일 서버가 설정되지 않았습니다.")
throw new InvalidInputException("메일 서버가 설정되지 않았습니다.")
}
def email = new Email(emailAddr)
email.setMimeType('text/html')
email.setSubject(subject)
email.setBody(body)
try {
// This is needed to avoid the exception about IMAPProvider
ContextClassLoaderSwitchingUtil.runInContext(SMTPMailServer.classLoader) {
mailServer.send(email)
}
logger.debug('Mail sent')
} catch (MailException e) {
logger.debug("Send mail failed with error: ${e.message}")
throw new InvalidInputException("메일 보내기에 실패했습니다.")
}
}
- 방법 2: body를 분할하여 저장
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.mail.Email
import com.atlassian.jira.mail.settings.MailSettings
import com.atlassian.mail.MailException
import com.atlassian.mail.server.SMTPMailServer
import com.atlassian.plugin.util.ContextClassLoaderSwitchingUtil
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.opensymphony.workflow.InvalidInputException
def issueManager = ComponentAccessor.getIssueManager()
// 이슈 Summary
def summaryfield = issue.getSummary()
// 그외 사용 할 변수 들
def variable1 = "칼럼1 변수"
def variable2 = "행1 변수"
def variable3 = "행2 변수"
def variable4 = "행3 변수"
// HTML 복사한 값 넣기
def body1 = """
<p style="text-align: center;"><strong>메일 템플릿</strong></p>
<p style="text-align: center;"><br></p>
<table style="width: 86%; margin: 0px auto; font-family: Calibri, sans-serif; border-collapse: collapse; border: 2px solid rgb(0, 0, 0);">
<tbody>
<tr>
<td style="width: 8.0675%; text-align: center; border: 2px solid rgb(0, 0, 0); background-color: rgb(239, 239, 239);">칼럼1</td>
<td style="width: 13.7802%; text-align: center; border: 2px solid rgb(0, 0, 0); background-color: rgb(239, 239, 239);">칼럼2</td>
<td style="width: 35.5014%; text-align: center; border: 2px solid rgb(0, 0, 0); background-color: rgb(239, 239, 239);">
<div style="text-align: center;">칼럼3</div>
</td>
<td style="width: 39.2953%; text-align: center; border: 2px solid rgb(0, 0, 0); background-color: rgb(239, 239, 239);">
<div style="text-align: center;">칼럼4</div>
</td>
</tr>
"""
def body2 = """
<tr>
<td rowspan="3" style="width: 8.042%; text-align: center; border: 2px solid rgb(0, 0, 0);">${variable1}</td>
<td style="width: 13.7802%; text-align: center; border: 2px solid rgb(0, 0, 0);">행1</td>
<td style="width: 35.5014%; text-align: center; border: 2px solid rgb(0, 0, 0);">${variable2}</td>
<td style="width: 39.2953%; text-align: center; border: 2px solid rgb(0, 0, 0);"><br></td>
</tr>
<tr>
<td style="width: 13.7802%; text-align: center; border: 2px solid rgb(0, 0, 0);">행2</td>
<td style="width: 35.5014%; text-align: center; border: 2px solid rgb(0, 0, 0);">${variable3}</td>
<td style="width: 39.2953%; text-align: center; border: 2px solid rgb(0, 0, 0);"><br></td>
</tr>
<tr>
<td style="width: 13.7802%; text-align: center; border: 2px solid rgb(0, 0, 0);">행3</td>
<td style="width: 35.5014%; text-align: center; border: 2px solid rgb(0, 0, 0);">${variable4}</td>
<td style="width: 39.2953%; text-align: center; border: 2px solid rgb(0, 0, 0);"><br></td>
</tr>
</tbody>
</table>
<p><br></p>
"""
def body = body1 + body2
//메일 받는 사람 설정(현재는 해당 이슈 담당자로 설정)
def userManager = ComponentAccessor.getUserManager()
def user = issue.getAssignee()
//기본 메일 주소 설정, 담당자 없을 시 보고자로 설정
if(user == null) {
user = issue.getReporter()
}
def receiver = user.getEmailAddress()
// 메일주소, 메일 제목, 내용
sendEmail(receiver.toString(), summary ,body)
// 메일보내기 함수
String sendEmail(String emailAddr, String subject, String body) {
def logger = Logger.getLogger(getClass())
logger.setLevel(Level.DEBUG)
// Stop emails being sent if the outgoing mail server gets disabled (useful if you start a script sending emails and need to stop it)
def mailSettings = ComponentAccessor.getComponent(MailSettings)
if (mailSettings?.send()?.disabled) {
logger.debug("메일 서버가 비활성 상태입니다.")
throw new InvalidInputException("메일 서버가 비활성 상태입니다.")
}
def mailServer = ComponentAccessor.mailServerManager.defaultSMTPMailServer
if (!mailServer) {
logger.debug("메일 서버가 설정되지 않았습니다.")
throw new InvalidInputException("메일 서버가 설정되지 않았습니다.")
}
def email = new Email(emailAddr)
email.setMimeType('text/html')
email.setSubject(subject)
email.setBody(body)
try {
// This is needed to avoid the exception about IMAPProvider
ContextClassLoaderSwitchingUtil.runInContext(SMTPMailServer.classLoader) {
mailServer.send(email)
}
logger.debug('Mail sent')
} catch (MailException e) {
logger.debug("Send mail failed with error: ${e.message}")
throw new InvalidInputException("메일 보내기에 실패했습니다.")
}
}




