Table

ESAMTML Table을 사용하지 않고 기존 ESAMAIL Table에 컬럼추가

 

CommonMailService.java

package smartsuite.app.common.mail;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Future;

import javax.inject.Inject;

import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import smartsuite.app.bp.admin.template.TemplateService;
import smartsuite.app.common.TemplateGeneratorService;
import smartsuite.app.common.mail.data.MailInfo;
import smartsuite.app.common.mail.receiver.MailReceiver;

/**
 * 공통 메일 API 작성
 *
 * @author JongHyeok Choi
 * @see 
 * @FileName CommonMailService.java
 * @package smartsuite.app.common.mail
 * @Since 2016. 8. 1
 * @변경이력 : [2016. 8. 1] JongHyeok Choi 최초작성
 */
@Service
@SuppressWarnings ({ "unchecked" })
@Transactional
public class CommonMailService {

    static final Logger LOG = LoggerFactory.getLogger(CommonMailService.class);
    
    /** The sql session. */
    @Inject
    private SqlSession sqlSession;
    
    /** Template */
    @Inject
    private TemplateGeneratorService templateGeneratorService;

    @Inject
    private TemplateService templateService;
    
    /** SMTP  */
    @Inject
    private JavaSmtpMailSender javaSmtpMailSender;
    
    @Inject
    private MailReceiver mailReceiver;
    
    @Value ("#{globalProperties['server.env.cls']}")
    private String serverEnvCls;
    
    @Value ("#{globalProperties['site.name']}")
    private String siteName;
    
    @Value("#{globalProperties['bp.url']}")
    private String bpUrl;
    
    @Value("#{globalProperties['sp.url']}")
    private String spUrl;
    
    @Value ("#{mail['mail.smtp.domain']}")
    private String domain;
    
    /** Mail Sender Default Email Address */
    @Value("#{mail['mail.sender.address']}")
    private String fromAddress;
    
    /** Mail Sender Default Name */
    @Value("#{mail['mail.sender.name']}")
    private String fromName;
    
    /** Mapper Namespace */
    private static final String NAMESPACE = "mail.";
    
    /**
     * 
     * (비동기 방식)
     * 메일 단일 전송
     * 
     *
     * @author : JongHyeok Choi
     * @param 메일 Key, 메일 내용
     * @return void
     * @Date : 2016. 8. 1
     * @Method Name : addMail
     */
    @Async
    public Future<String> addMail(String mailKey, Map<String, Object> mail)
    {
        if (mail == null || mail.isEmpty()) {
            return new AsyncResult<String>("fail");
        }
        
        // to_list : [{"to_addr":"honggd@emro.co.kr", "to_nm":"홍길동", "to_type":"TO"}, {"to_addr":"kimgd@emro.co.kr", "to_nm":"김길동", "to_type":"CC"}]
        List<Map<String, Object>> toList  = (List<Map<String, Object>>)mail.get("to_list");
        
        return addMail(mailKey, mail, toList);
    }
    
    @Async
    public Future<String> addMail(String mailKey, Map<String, Object> mail, List<Map<String, Object>> toList)
    {
        if (mail == null || mail.isEmpty() || toList == null || toList.isEmpty()) {
            return new AsyncResult<String>("fail");
        }
       
        this.sendMail(mailKey, mail, toList);
        
        return new AsyncResult<String>("success"); 
    }
    
    /**
     * 
     * (비동기 방식)
     * 보낼 메일을 ESAMAIL에 저장
     * 실시간 전송일 경우 바로 전송
     *
     * @author : JongHyeok Choi
     * @param 메일 Key, 메일 내용
     * @return void
     * @Date : 2016. 8. 1
     * @Method Name : addMail
     */
    @Async
    private Future<String> sendMail(String mailKey, Map<String, Object> mail, List<Map<String, Object>> toList)
    {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("mail_set_id", mailKey);
        Map<String, Object> mailTmpl = sqlSession.selectOne(NAMESPACE + "findListMailByMailId", param);
        String useYn    = (String)mailTmpl.get("use_yn");
        String sndCls   = (String)mailTmpl.get("snd_cls");
        
        // useYn이 N일 경우 데이터 생성 X
        if ("N".equals(useYn)) {
            return new AsyncResult<String>("not use");
        }
        
        Map<String, Object> tmpl = templateService.findTemplateBaseById(mailTmpl);
        
        try {
            mail.put("mail_grp_id"  , UUID.randomUUID().toString());
            mail.put("mail_set_id"  , mailKey);
            mail.put("from_nm"      , mail.get("from_nm")   == null ? fromName      : mail.get("from_nm"));  // 송신자 이름
            mail.put("from_addr"    , mail.get("from_addr") == null ? fromAddress   : mail.get("from_addr"));// 송신자 주소
            
            // 메일 데이터
            Map<String, Object> _data = (Map<String, Object>)mail.get("data");

            // 메일 제목
            String mailTit = templateGeneratorService.mailGenerateTitle(mailKey, _data);
            mail.put("mail_tit"     , mailTit);
            
            // 메일 본문
            _data.put("site_name"   , _data.get("site_name")== null ?  siteName     : _data.get("site_name"));
            _data.put("site_url"    , _data.get("site_url") == null ?  spUrl        : _data.get("site_url"));
            String mailCont = templateGeneratorService.mailGenerate(mailKey, _data);
            
            // 메일 base template
            tmpl.put("site_name"    , _data.get("site_name"));
            tmpl.put("site_url"     , _data.get("site_url"));
            tmpl.put("contents"     , mailCont);
            
            //Base Template 반영
            mail.put("mail_cont", templateGeneratorService.generate(mailKey, (String)tmpl.get("tmp_bas_cont"), tmpl));

            //DB Insert
            for (Map<String, Object> _to : toList) {
                // 개발용
                if (Lists.newArrayList("DEV", "LOCAL").contains(serverEnvCls)) {
                    if (!Lists.newArrayList("anzinda76@emro.co.kr").contains(_to.get("to_addr"))) {
                        _to.put("to_addr", "anzinda76@emro.co.kr");
                    }
                }
                
                mail.put("mail_id"  , UUID.randomUUID().toString());
                mail.put("to_addr"  , _to.get("to_addr"));  // 수신자 주소
                mail.put("to_nm"    , _to.get("to_nm"));    // 수신자 이름
                mail.put("to_type"  , _to.get("to_type"));  // 수신 구분
                mail.put("snd_yn"   , "N");                 // 전송 여부
                
                this.insertEsamail(mail);
            }
            
            //실시간 전송, 배치일 경우 스케쥴러에 의해 전송
            if ("R".equals(sndCls)) {
                this.realTimeTransfer(mail);
            }
        
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
        
        return new AsyncResult<String>("success");
    }
    
    public List<MailInfo> getMail() throws Exception{
        return mailReceiver.receiveEmail(new Date(1551279600000L));
    }
    
    /**
     * ESAMAIL에 보낼 메일을 저장
     *
     * @author : JongHyeok Choi
     * @param 메일 저장
     * @return void
     * @Date : 2016. 8. 1
     * @Method Name : insertEsamail
     */
    private void insertEsamail(Map<String, Object> mail) {
        sqlSession.insert(NAMESPACE + "insertEsamail", mail);
    }

    /**
     * 메일 실시간 전송
     *
     * @author : JongHyeok Choi
     * @param 메일 내용
     * @return void
     * @Date : 2016. 8. 1
     * @Method Name : realTimeTransfer
     */
    private void realTimeTransfer(Map<String, Object> mail) {
        this.send(mail);
    }
    
    /**
     * 배치 방식 메일 전송
     *
     * @author : JongHyeok Choi
     * @param 메일 저장
     * @return void
     * @Date : 2016. 8. 1
     * @Method Name : batchMail
     */
    public void batchMail(HashMap<String,Object> param) {
        List<Map<String, Object>> mailList = sqlSession.selectList(NAMESPACE + "findListSendMail", param); 
        
        for(Map<String, Object> mail : mailList){
            this.send(mail);
        }
    }

    /**
     * 메일 전송 및 전솔 결과 업데이트
     *
     * @author : JongHyeok Choi
     * @param 메일 저장
     * @return void
     * @Date : 2016. 8. 1
     * @Method Name : send
     */
    private void send(Map<String, Object> mail)
    {
        List<String>                _idListInt  = Lists.newArrayList();
        List<Map<String, Object>>   _toListInt  = Lists.newArrayList();
        
        List<String>                _idListExt  = Lists.newArrayList();
        List<Map<String, Object>>   _toListExt  = Lists.newArrayList();
        
        List<Map<String, Object>> _mailList = sqlSession.selectList(NAMESPACE + "findESAMailById", mail);

        for (Map<String, Object> _mail : _mailList)
        {
            Map<String, Object> _to = Maps.newHashMap();
            _to.put("to_addr" , _mail.get("to_addr"));
            _to.put("to_nm"   , _mail.get("to_nm"));
            _to.put("to_type" , _mail.get("to_type"));
            
            // 내/외부 분리전송
            String _toAddr = (String)_mail.get("to_addr"); 
            
            if (domain.equals(_toAddr.substring(_toAddr.indexOf("@") + 1)))
            {
                _idListInt.add((String)_mail.get("mail_id"));
                _toListInt.add(_to);
            }
            else
            {
                _idListExt.add((String)_mail.get("mail_id"));
                _toListExt.add(_to);
            }
        }
        
        // 1. 내부메일발송
        if (!_toListInt.isEmpty())
        {
            try
            {
                mail.put("mail_ids" , _idListInt);
                mail.put("to_list"  , _toListInt);
                javaSmtpMailSender.sendInt(mail);
                
                mail.put("snd_yn"   , "Y");
            }
            catch(Exception e)
            {
                mail.put("snd_yn"   , "N");

                LOG.error(e.getMessage(), e);
            }
            finally
            {
                sqlSession.update(NAMESPACE + "updateSendComplete", mail);
            }
        }

        // 2. 외부메일발송
        if (!_toListExt.isEmpty())
        {
            try
            {
                mail.put("mail_ids" , _idListExt);
                mail.put("to_list"  , _toListExt);
                javaSmtpMailSender.sendExt(mail);
                
                mail.put("snd_yn"   , "Y");
            }
            catch(Exception e)
            {
                mail.put("snd_yn"   , "N");
                
                LOG.error(e.getMessage(), e);
            }
            finally
            {
                sqlSession.update(NAMESPACE + "updateSendComplete", mail);
            }
        }
    }
}

 

JavaSmtpMailSender.java

package smartsuite.app.common.mail;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;

import smartsuite.upload.core.entity.FileItem;
import smartsuite.upload.core.entity.FileList;
import smartsuite.upload.core.service.FileService;

import javax.activation.DataHandler;
import javax.inject.Inject;
import javax.mail.*;
import javax.mail.Message.RecipientType;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;

@Service
public class JavaSmtpMailSender {

    static final Logger LOG = LoggerFactory.getLogger(JavaSmtpMailSender.class);
    
    @Value ("#{mail['mail.smtp.encoding']}")
    String encoding;

    @Value ("#{mail['mail.smtp.host']}")
    String host;
       
    @Value ("#{mail['mail.smtp.port']}")
    String port;

    @Value ("#{mail['mail.smtp.host.ext']}")
    String hostExt;
    
    @Value ("#{mail['mail.smtp.port.ext']}")
    String portExt;
    
    @Value ("#{mail['mail.smtp.username']}")
    String username;
    
    @Value ("#{mail['mail.smtp.password']}")
    String password;
    
    @Value ("#{mail['mail.smtp.socketFactory.class']}")
    String smtpSocketFactoryClass;
    
    @Inject
    FileService fileService;

    boolean debug; //Session Debug 
    
    protected boolean requireAuthenticate() {
        return username != null && password != null;
    }

    protected Authenticator createAuthenticator() {
        return new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        };
    }
    
    // For Internal SMTP
    protected Properties createProperties() {
        Properties properties = new Properties();
        properties.put("mail.smtp.host", host);
        properties.put("mail.smtp.port", port);

        if(StringUtils.isNotEmpty(smtpSocketFactoryClass)){
            properties.put("mail.smtp.socketFactory.class", smtpSocketFactoryClass);
            properties.put("mail.smtp.auth", "false");
        }else {
            properties.put("mail.smtp.auth", this.requireAuthenticate());
        }
        
        return properties;
    }

    // For External SMTP
    protected Properties createPropertiesExt() {
        Properties properties = new Properties();
        properties.put("mail.smtp.host", hostExt);
        properties.put("mail.smtp.port", portExt);

        if(StringUtils.isNotEmpty(smtpSocketFactoryClass)){
            properties.put("mail.smtp.socketFactory.class", smtpSocketFactoryClass);
            properties.put("mail.smtp.auth", "false");
        }else {
            properties.put("mail.smtp.auth", this.requireAuthenticate());
        }
        
        return properties;
    }
       
    private Address createAddress(String address, String name) throws UnsupportedEncodingException {
        InternetAddress ia = new InternetAddress(address, name);
        
        String personal = ia.getPersonal();
        if(personal != null){
            ia.setPersonal(personal, encoding);
        }
        return ia;
    }

    public void multiSend(Map<String, Object> mail) throws MessagingException, UnsupportedEncodingException {
        Session session = null;
        if (requireAuthenticate()) {
            try {
                session = Session.getDefaultInstance(createProperties(), createAuthenticator());
            } catch (SecurityException exception) {
                LOG.debug("메일서버(SMTP)가 연동되어 있지 않습니다.");
            }
        } else {
            session = Session.getDefaultInstance(createProperties());
        }
        session.setDebug(debug);
        MimeMessage message = new MimeMessage(session);
        Multipart multiPart = new MimeMultipart();

        Address from = createAddress((String)mail.get("from_addr"), (String)mail.get("from_nm"));
        message.setFrom(from);
        message.setSubject((String)mail.get("mail_tit"), encoding);

        //TO 주소 목록
        String toAddressList = mail.get("to_addr_list") == null ? "" : mail.get("to_addr_list").toString();
        String toAddressNameList = mail.get("to_nm_list") == null ? "" : mail.get("to_nm_list").toString();

        if(StringUtils.isNotEmpty(toAddressList) && toAddressList.indexOf(",") > -1){
            String[] toAddress = toAddressList.split(",");
            String[] toNames = toAddressNameList.split(",");

            Address[] addressList = new Address[toAddress.length];
            for(int a = 0; a < toAddress.length; a++){
                addressList[a] = createAddress(toAddress[a], toNames[a]);
            }
            message.addRecipients(RecipientType.TO,addressList);

        }else{
            // to address가 list(,) 형태가 아닌 단일 형태로 본다.
            message.addRecipient(RecipientType.TO, createAddress(toAddressList, toAddressNameList));
        }

        //CC 주소 목록
        String ccAddressList = mail.get("cc_addr_list") == null ? "" : mail.get("cc_addr_list").toString();
        String ccAddressNameList = mail.get("cc_nm_list") == null ? "" : mail.get("cc_nm_list").toString();

        if(StringUtils.isNotEmpty(ccAddressList) && ccAddressList.indexOf(",") > -1){
            String[] ccAddress = ccAddressList.split(",");
            String[] ccNames = ccAddressNameList.split(",");

            Address[] addressList = new Address[ccAddress.length];
            for(int a = 0; a < ccAddress.length; a++){
                addressList[a] = createAddress(ccAddress[a], ccNames[a]);
            }
            message.addRecipients(RecipientType.CC,addressList);

        }else{
            // CC address가 list(,) 형태가 아닌 단일 형태로 본다.
            message.addRecipient(RecipientType.CC, createAddress(ccAddressList, ccAddressNameList));
        }

        //BCC 주소 목록
        String bccAddressList = mail.get("bcc_addr_list") == null ? "" : mail.get("bcc_addr_list").toString();
        String bccAddressNameList = mail.get("bcc_nm_list") == null ? "" : mail.get("bcc_nm_list").toString();

        if(StringUtils.isNotEmpty(bccAddressList) && bccAddressList.indexOf(",") > -1){
            String[] bccAddress = bccAddressList.split(",");
            String[] bccNames = bccAddressNameList.split(",");

            Address[] addressList = new Address[bccAddress.length];
            for(int a = 0; a < bccAddress.length; a++){
                addressList[a] = createAddress(bccAddress[a], bccNames[a]);
            }
            message.addRecipients(RecipientType.BCC,addressList);

        }else{
            // BCC address가 list(,) 형태가 아닌 단일 형태로 본다.
            message.addRecipient(RecipientType.BCC, createAddress(bccAddressList, bccAddressNameList));
        }
        MimeBodyPart body = new MimeBodyPart();
        body.setHeader("Content-Transfer-Encoding", "base64");
        body.setContent((String)mail.get("mail_cont"), "text/html; charset=\""
                + encoding + "\"");
        multiPart.addBodyPart(body);

        /*
         * 첨부파일 존재시
         * */
        FileList fileList;
        try {
            fileList = fileService.findDownloadList((String)mail.get("grp_cd"));
        
            for (FileItem fileItem : fileList.getItems()) {
                ByteArrayDataSource dataSource;
                dataSource = new ByteArrayDataSource(fileItem.toInputStream(), "application/octet-stream");
                String attachmentName = MimeUtility.encodeText(
                        fileItem.getName(), encoding, "B");
                MimeBodyPart attachmentBody = new MimeBodyPart();
                attachmentBody.setHeader("Content-Transfer-Encoding", "base64");
                attachmentBody.setDataHandler(new DataHandler(dataSource));
                attachmentBody.setFileName(attachmentName);
        
                multiPart.addBodyPart(attachmentBody);
            }
        } catch (Exception e) {
            LOG.error(e.getMessage());
        }
        
        message.setContent(multiPart);
        message.setSentDate(new Date());
        
        Transport.send(message);
    }

    public void sendInt(Map<String, Object> mail) throws MessagingException, UnsupportedEncodingException
    {
        Session session = null;
        
        if (this.requireAuthenticate())
        {
            try
            {
                session = Session.getInstance(this.createProperties(), this.createAuthenticator());
            }
            catch (SecurityException exception)
            {
                LOG.debug("내부메일서버(SMTP)가 연동되어 있지 않습니다.");
            }
        }
        else
        {
            session = Session.getDefaultInstance(this.createProperties());
        }
        
        this.send(mail, session);
    }

    public void sendExt(Map<String, Object> mail) throws MessagingException, UnsupportedEncodingException
    {
        Session session = null;
        
        if (this.requireAuthenticate())
        {
            try
            {
                session = Session.getInstance(this.createPropertiesExt(), this.createAuthenticator());
            }
            catch (SecurityException exception)
            {
                LOG.debug("외부메일서버(SMTP)가 연동되어 있지 않습니다.");
            }
        }
        else
        {
            session = Session.getDefaultInstance(this.createPropertiesExt());
        }
        
        this.send(mail, session);
    }
    
    private void send(Map<String, Object> mail, Session session) throws MessagingException, UnsupportedEncodingException
    {
        session.setDebug(debug);
        MimeMessage message = new MimeMessage(session);
        Multipart multiPart = new MimeMultipart();

        Address from = createAddress((String)mail.get("from_addr"), (String)mail.get("from_nm"));
        message.setFrom(from);
        message.setSubject((String)mail.get("mail_tit"), encoding);

        List<Map<String, Object>> _toList   = (List<Map<String, Object>>)mail.get("to_list");
        List<Map<String, Object>> toList    = Lists.newArrayList();
        List<Map<String, Object>> ccList    = Lists.newArrayList();
        List<Map<String, Object>> bcList    = Lists.newArrayList();
        
        for (Map<String, Object> _to : _toList)
        {
            switch ((String)_to.get("to_type"))
            {
                case "TO" :
                    toList.add(_to);
                    break;
                    
                case "CC" :
                    ccList.add(_to);
                    break;
                    
                case "BCC" :
                    bcList.add(_to);
                    break;
            }
        }
        
        // 1. TO
        if (!toList.isEmpty())
        {
            Address[] toAddress = new Address[toList.size()];
            
            for (int i = 0; i < toList.size(); i++)
            {
                Map<String, Object>_addr = toList.get(i);
                toAddress[i] = this.createAddress((String)_addr.get("to_addr"), (String)_addr.get("to_nm"));
            }
            
            message.addRecipients(RecipientType.TO, toAddress);
        }

        // 2. CC
        if (!ccList.isEmpty())
        {
            Address[] ccAddress = new Address[ccList.size()];
            
            for (int i = 0; i < ccList.size(); i++)
            {
                Map<String, Object>_addr = ccList.get(i);
                ccAddress[i] = this.createAddress((String)_addr.get("to_addr"), (String)_addr.get("to_nm"));
            }
            
            message.addRecipients(RecipientType.CC, ccAddress);
        }
        
        // 3. BCC
        if (!bcList.isEmpty())
        {
            Address[] bcAddress = new Address[bcList.size()];
            
            for (int i = 0; i < bcList.size(); i++)
            {
                Map<String, Object>_addr = bcList.get(i);
                bcAddress[i] = this.createAddress((String)_addr.get("to_addr"), (String)_addr.get("to_nm"));
            }
            
            message.addRecipients(RecipientType.BCC, bcAddress);
        }
        
        MimeBodyPart body = new MimeBodyPart();
        body.setHeader("Content-Transfer-Encoding", "base64");
        body.setContent((String)mail.get("mail_cont"), "text/html; charset=\"" + encoding + "\"");
        multiPart.addBodyPart(body);

        // 첨부파일 처리
        FileList fileList;
        try
        {
            fileList = fileService.findDownloadList((String)mail.get("grp_cd"));

            for (FileItem fileItem : fileList.getItems())
            {
                ByteArrayDataSource dataSource;
                dataSource = new ByteArrayDataSource(fileItem.toInputStream(), "application/octet-stream");
                String attachmentName = MimeUtility.encodeText(fileItem.getName(), encoding, "B");
                
                MimeBodyPart attachmentBody = new MimeBodyPart();
                attachmentBody.setHeader("Content-Transfer-Encoding", "base64");
                attachmentBody.setDataHandler(new DataHandler(dataSource));
                attachmentBody.setFileName(attachmentName);

                multiPart.addBodyPart(attachmentBody);
            }
        }
        catch (Exception e)
        {
            LOG.error(e.getMessage());
        }

        message.setContent(multiPart);
        message.setSentDate(new Date());

//        System.out.println("SMTP =================================");
//        System.out.println(session.getProperty("mail.smtp.host"));
//        System.out.println(session.getProperty("mail.smtp.port"));
//        
//        System.out.println("toList =================================");
//        System.out.println(toList);
//        
//        System.out.println("ccList =================================");
//        System.out.println(ccList);
//        
//        System.out.println("bcList =================================");
//        System.out.println(bcList);
        
        Transport.send(message);
    }

    public static class DefaultAuthenticator extends Authenticator {

        private final PasswordAuthentication authentication;

        public DefaultAuthenticator(String username, String password) {
            super();
            this.authentication = new PasswordAuthentication(username, password);
        }

        protected PasswordAuthentication getPasswordAuthentication() {
            return this.authentication;
        }
    }
}

 

 

화면

em-mail.html

<sc-link rel="import" href="es-mail-list.html"></sc-link>
<sc-link rel="import" href="es-mail-form.html"></sc-link>
<sc-link rel="import" href="es-mail-history.html"></sc-link>
<sc-link rel="import" href="es-multi-mail-history.html"></sc-link>

<dom-module id="em-mail">
    <style>
        :host {
            @apply(--vbox-layout);
        }
    </style>
    
    <template>
    	<cc-page-title-bar></cc-page-title-bar>
    	<div class="hbox flex">
	        <es-mail-list id="list" on-selected-mail="onFindMailList" on-add-mail="onAddMail" on-delete-mail="onDeleteMail" class="flex-4"></es-mail-list>
	        <sc-splitter split-type="vertical"></sc-splitter>
	        <sc-tab-navigation id="tabNavi" class="flex-6">
	            <es-mail-form id="form" title-text="메일양식" on-save-mail="onSaveMailList"></es-mail-form>
	            <es-mail-history id="history" title-text="메일전송이력"></es-mail-history>
	            <es-multi-mail-history id="multiHistory" title-text="메일다중전송이력" hidden="true"></es-multi-mail-history>
	        </sc-tab-navigation>
    	</div>
    </template>
    
    <script>
        Polymer({
            is: 'em-mail',
            
            // 메일목록 : 메일아이디 선택
            onFindMailList: function(e, data){
                var me = this;
                me.$.form.load(data);
                me.$.history.load(data);
                me.$.multiHistory.load(data);
            },
            
            // 메일목록 : 추가
            onAddMail: function(){
                var me = this;
                
                me.$.form.addMailForm();
            },
            
         	// 메일목록 : 삭제
            onDeleteMail: function(){
                var me = this;
                me.$.form.onClear();
                me.$.history.reset();
                me.$.multiHistory.reset();
            },
            
            // 메일양식 : 저장 완료
            onSaveMailList: function(){
                var me = this;
                me.$.list.onSearch();
            }
            
        });
    </script>

</dom-module>

 

es-mail-list.html

<dom-module id="es-mail-list">
	<style>
		:host {
			@apply(--vbox-layout);
		}
	</style>

	<template>
		<!-- 메일 목록 그리드 조회 -->
		<sc-ajax id="findList"
				 url="findListMail.do"
				 body="{{searchParam}}"
				 last-response="{{resultList}}">
		</sc-ajax>

		<!-- 메일 목록 그리드 삭제 -->
		<sc-ajax id="deleteList"
				 url="deleteListMail.do"
				 on-response="completeDeleteList">
		</sc-ajax>

		<cc-auth-checker check-list="auth-r, auth-s"></cc-auth-checker>

		<sc-grid id="gridPanel" data-provider="{{resultList}}" editable="true" class="flex" use-state="false" show-tooltip="true"
				 on-item-click="onItemClick">
			
            <cc-grid-toolbar title-text="메일목록">
				<sc-button text="추가" on-click="onAddMail" auth-s></sc-button>
				<sc-button text="삭제" on-click="onDeleteList" auth-s></sc-button>
                <div class="hspace-10"></div>
                <sc-button auth-r tooltip="새로고침" on-click="onSearch" class="btnRefresh"></sc-button>
			</cc-grid-toolbar>
            
			<sc-grid-columns>
                <sc-data-column data-field="tmp_bas_nm"  header-text="메일템플릿" width="160" text-align="center" show-default-content-tooltip="true"></sc-data-column>
				<sc-data-column data-field="mail_set_id" header-text="메일아이디" width="200" text-align="center" style-name="link"></sc-data-column>
				<sc-data-column data-field="mail_set_nm" header-text="메일명" width="250" text-align="left" show-default-content-tooltip="true"></sc-data-column>
                <sc-date-column header-text="수정일시"
                                data-field="mod_dt"                 width="130"             text-align="center"
                                format-type="datetime"></sc-date-column>
                <sc-date-column header-text="최근전송일시"
                                data-field="snd_dt"                 width="130"             text-align="center"
                                format-type="datetime"></sc-date-column>
			</sc-grid-columns>
		</sc-grid>

	</template>

	<script>
        Polymer({
            is: 'es-mail-list',

            properties:{
                // 조회 조건
				searchParam: {
				  	type: Object,
					value : function() {
				  	    return {};
					}
				},
				// 조회 결과
				resultList: {
				    type: Array,
					value: function() {
				        return [];
					}
				}
            },

            /******************************
             * 초기화 설정
             ******************************/
			// 초기화 완료 후 호출 함수
            initialized: function(){
                var me = this;
                me.onSearch();
            },

            /******************************
             * 그리드 이벤트
             ******************************/
            // 그리드 cell click 이벤트
            onItemClick: function(event) {
                var me = this,
                    data = event.detail.data,
                    item = event.detail.item;

                if(item.dataField === "mail_set_id"){
                    me.fire("selected-mail", data);
                }
            },

            /******************************
             * 버튼 이벤트
             ******************************/
            // 조회
            onSearch: function(){
                var me = this;
                UT.request(me.$.findList);
            },

			// 삭제
            onDeleteList: function(){
                var me = this,
                    provider = me.$.gridPanel.getDataProvider(),
                    checked = provider.selectionCheckedIndexes();

                if (checked.length === 0) { // "선택된 항목이 없습니다",
                    UT.alert("STD.N1600");
                    return;
                }

                UT.confirm("STD.N1300", function() { // "삭제 하시겠습니까?"
                    var deleted = provider.removeItems();
                    if(deleted.length > 0){
                        me.$.deleteList.body = {
                            deleteMail: deleted
                        };
                        UT.request(me.$.deleteList);
                    }
                });

            },

            // 삭제 완료
            completeDeleteList: function(){
                var me = this;
				UT.alert("STD.N2500", function(){ // 삭제하였습니다.
					me.onSearch(); // 재조회
					me.fire("delete-mail");
				});
            },

			// 메일 양식 추가
            onAddMail: function(){
                var me = this;
                me.fire("add-mail");
            }

        });
	</script>

</dom-module>

 

es-mail-form.html

<sc-link rel="import" href="../tmp/ep-tmp-preview.html"></sc-link>
<sc-link rel="import" href="ep-mail-send-test.html"></sc-link>

<dom-module id="es-mail-form">
	<style>
		:host {
			@apply(--vbox-layout);
		}
	</style>

	<template>
		<!-- 코드 조회 -->
		<sc-request-group init>
			<!-- 공통코드 조회 -->
			<sc-code-group>
				<sc-code id="findListCode" code="C009" value="{{codes.use_yn}}" ></sc-code> <!-- 사용여부 -->
				<sc-code id="findListCode" code="C015" value="{{codes.snd_cls}}" ></sc-code> <!-- 메일전송구분 -->
			</sc-code-group>
			<!-- 콤보박스 템플릿 목록 -->
			<sc-ajax url="getAllTmpBasIdList.do"
					 last-response="{{codes.template}}">
			</sc-ajax>
		</sc-request-group>

		<!-- 조회 -->
		<sc-ajax id="findListMailByMailId"
				 url="findListMailByMailId.do"
				 last-response="{{mailInfo}}"
				 on-response="completeFindInfoMail">
		</sc-ajax>

		<!-- 템플릿 조회 -->
		<sc-ajax id="findTmpByTmpId"
				 url="findTmpByTmpId.do"
				 on-response="completeFindInfoTmp">
		</sc-ajax>

		<!-- 저장 -->
		<sc-ajax id="saveList"
				 url="saveListMail.do"
				 body="{{mailInfo}}"
				 on-response="completeSaveListMail">
		</sc-ajax>

		<cc-auth-checker check-list="auth-r, auth-s"></cc-auth-checker>

		<cc-sub-title-bar>
			<sc-button text="저장" on-click="onSaveList" auth-s></sc-button>
		</cc-sub-title-bar>
		<table class="tb-form">
			<colgroup>
				<col style="width:100px">
				<col>
				<col style="width:100px">
				<col>
			</colgroup>
            <tr>
                <th><sc-label text="메일템플릿"></sc-label></th>
                <td>
                    <sc-combobox-field
                            display-field="tmp_bas_nm" value-field="tmp_bas_id"
                            items="{{codes.template}}" value="{{mailInfo.tmp_bas_id}}" placeholder="선택" 
                            required="[[formula('isEditable')]]" readonly="[[!formula('isEditable')]]">
                    </sc-combobox-field>
                </td>
                <th>
                    <sc-label text="수정일시"></sc-label>
                </th>
                <td>
                    <cc-datetime-field value="{{mailInfo.mod_dt}}"></cc-datetime-field>
                </td>
            </tr>
			<tr>
				<th><sc-label text="메일아이디"></sc-label></th>
				<td>
					<sc-text-field value="{{mailInfo.mail_set_id}}" required="{{formula('isNew')}}" readonly="{{!formula('isNew')}}" max-length="36" mask-re="/[A-Za-z0-9_]/" strip-chars-re="/[ㄱ-힣]/" upper-case="true"></sc-text-field>
				</td>

				<th><sc-label text="사용여부"></sc-label></th>
				<td>
					<sc-combobox-field
							display-field="label" value-field="data"
							items="{{codes.use_yn}}" value="{{mailInfo.use_yn}}" placeholder="선택" 
                            required="[[formula('isEditable')]]" readonly="[[!formula('isEditable')]]">
					</sc-combobox-field>
				</td>
			</tr>

			<tr>
				<th><sc-label text="메일명"></sc-label></th>
				<td>
					<sc-text-field value="{{mailInfo.mail_set_nm}}" max-length="200" required="[[formula('isEditable')]]" readonly="[[!formula('isEditable')]]"></sc-text-field>
				</td>

				<th><sc-label text="전송구분"></sc-label></th>
				<td>
					<sc-combobox-field
							display-field="label" value-field="data"
							items="{{codes.snd_cls}}" value="{{mailInfo.snd_cls}}" placeholder="선택" 
                            required="[[formula('isEditable')]]" readonly="[[!formula('isEditable')]]">
					</sc-combobox-field>
				</td>
			</tr>
		</table>

		<cc-sub-title-bar title-text="템플릿">
			<sc-button text="미리보기" on-click="onPreview" auth-r></sc-button>
			<sc-button text="테스트메일보내기" on-click="openDialogTestMailData" auth-s></sc-button>
		</cc-sub-title-bar>
		<!-- 템플릿 에디터 -->
		<cc-source-editor id="editor" class="flex" value="{{mailInfo.tmp_cont}}" editable="true" view-hidden="false"></cc-source-editor>
	</template>

	<script>
        Polymer({
            is: 'es-mail-form',

            properties:{
				// 코드 데이터
                codes: {
                    type: Object,
					reset: false,
                    value: function() {
                        return {
							use_yn:[],
							snd_cls:[],
							template:[]
						};
                    }
                },
				// 메일 정보
                mailInfo: {
                    type: Object,
                    value: function() {
                        return {};
					}
                },
                tmpChangeReady: {
                    type: Boolean,
                    value: false
                },
                testMailInfo: {
                    type: Object,
					value: function () {
						return {
							to_nm: "",
							data: {}
						};
                    }
				}
            },

            formulas : {
                // 신규 상태
                isNew: function() {
                    return this.mailInfo.isNew === true;
                },

                // 수정 가능 상태 (신규 & 수정)
                isEditable : function() {
                    return (this.formula('isNew') || !UT.isEmpty(this.mailInfo.mail_set_id));
                }
            },

            /******************************
             * 초기화 설정
             ******************************/

            load: function(data){
                var me = this;

                me.$.findListMailByMailId.body = {
                    mail_set_id : data.mail_set_id
				};

                me.onFindInfoMail();
            },

            // 메일 양식 추가
            addMailForm: function(){
                var me = this;
                me.set("mailInfo", {});
                me.set("mailInfo.tmp_cont", "");
                me.set("mailInfo.isNew", true);

                me.applyFormula();
                me.$.editor.reset();
                me.$.editor.focus();
            },

            // 초기화
            onClear: function(){
                var me = this;
                me.reset();
                me.$.editor.reset();
                me.applyFormula();
            },

            /******************************
             * 버튼 이벤트
             ******************************/
            // 메일 상세 조회
            onFindInfoMail: function(){
                var me = this;
                me.set("tmpChangeReady", false); //Mail ID클릭시 onChangeTemplate이벤트가 발생하지 않도록
                UT.request(me.$.findListMailByMailId);
            },

            // 메일 조회 완료
            completeFindInfoMail: function(){
                var me = this;
                me.applyFormula();
            },

			// 저장
            onSaveList: function(){
                var me = this;

                if(!me.formula('isEditable')){
                    UT.alert(me.translate("STD.E1012",null,me.translate('메일아이디')),null,true); //"'{0}'을(를) 선택하십시오"
					return;
                }

                if(!me.validate()){
                    UT.alert("STD.E0000"); // 입력하신 정보를 다시 확인하여 주세요.
                    return;
                }

                UT.confirm("STD.N1200", function() { // 저장 하시겠습니까?
                    me.$.editor.syncValue();

                    UT.request(me.$.saveList);
                })
            },

            // 저장 완료
            completeSaveListMail: function(){
                var me = this;
				UT.alert("STD.N2400", function(){ // 저장하였습니다.
					me.fire("save-mail");

					me.$.findListMailByMailId.body = {
						mail_set_id : me.mailInfo.mail_set_id
					};

					me.onFindInfoMail();
				});
            },

            // 미리보기 팝업
            onPreview: function() {
                var me = this;

                if(!me.formula('isEditable')){
                    UT.alert(me.translate("STD.E1012",null,me.translate('메일아이디')),null,true); //"'{0}'을(를) 선택하십시오"
                    return;
                }

                me.$.editor.syncValue();

                var defaultParam = {
                    tmp_cls 		: 'TM'								// 템플릿 구분(TM:메일양식)
                    ,tmp_bas_id 	: me.mailInfo.tmp_bas_id			// 템플릿 코드(템플릿 기초 아이디)
                  	,app_id			: me.mailInfo.mail_set_id 			// id
                  	,contents		: me.mailInfo.tmp_cont || ""		// 템플릿 안의 내용
                };

                var tmpPopup = UT.popup('ep-tmp-preview', me, 1000, 800, {}, {titleText : "미리보기"});
                tmpPopup.show();
                tmpPopup.getWindowContent().load({defaultParam:defaultParam});
            },

            //템플릿 변경시 로드하기
            onChangeTemplate: function(e, data) {
                var me = this;

                if(me.get("tmpChangeReady")) {
                    UT.confirm("STD.ADM1001", function() {
                        me.set("mailInfo.tmp_cont", "");

                        me.$.findTmpByTmpId.body = {
                            tmp_bas_id :  data.value
                        };

                        UT.request(me.$.findTmpByTmpId);
                    }, function() {

                    });
                }
                me.set("tmpChangeReady", false);
            },

            //템플릿 직접 변경할 때에만 
            onTmpChangeReady: function() {
                var me = this;
                me.set("tmpChangeReady", true);
            },

            //템플릿 변경 조회 완료
            completeFindInfoTmp: function(e, res){
                var me = this,
					result = res.response;
                me.set("mailInfo.tmp_cont", result.tmp_bas_cont);
            },

			//메일 연동 테스트를 위한 Dialog
			openDialogTestMailData: function () {
				var me = this;
                me.set("testMailInfo.mailKey", me.mailInfo.mail_set_id);

                //Mail ID는 반드시 선택되어 있어야 함
                if(!(me.testMailInfo && me.testMailInfo.mailKey)) {
                    UT.alert("메일ID를 먼저 선택해주세요.", null, true);
                    return;
                }

                var mailSendTestPopup = UT.popup("ep-mail-send-test", me, 700, 900);
                mailSendTestPopup.show();
                mailSendTestPopup.getWindowContent().load(me.mailInfo.mail_set_id, function() {
                    me.$.editor.syncValue();
                    return me.$.editor.value;
				});
            }
        });
	</script>

</dom-module>

 

es-mail-history.html

<sc-link rel="import" href="/ui/bp/shared/ep-html-view.html"></sc-link>

<dom-module id="es-mail-history">
    <style>
        :host {
            @apply(--vbox-layout);
        }
    </style>

    <template>
        <!-- 조회 -->
        <sc-ajax id="findListHistory"
                 url="findListHistory.do"
                 body="{{searchParam}}"
                 on-response="onResponse">
        </sc-ajax>

        <!-- 공통코드 조회( C009 : 사용여부, C015: 메일전송구분, C011: 메일수신구분) -->
        <sc-code-group>
            <sc-code code="C009" value="{{codes.snd_yn}}"></sc-code>
            <sc-code code="C015" value="{{codes.snd_cls}}"></sc-code>
            <sc-code code="C011" value="{{codes.C011}}"></sc-code>
        </sc-code-group>

        <cc-auth-checker check-list="auth-r, auth-s"></cc-auth-checker>

        <cc-search-container on-search="onSearch" auth-r>
            <table>
                <colgroup>
                    <col style="width:120px">
                    <col>
                </colgroup>
                <tr>
                    <th><sc-label text="전송일자"></sc-label></th>
                    <td>
                        <sc-period-date-field from-value="{{searchParam.from_date}}" to-value="{{searchParam.to_date}}"
                                               default-from-value="-1M" string-date="false" on-enter="onSearch"
                                               from-required="true"></sc-period-date-field>
                    </td>
                </tr>
            </table>
        </cc-search-container>

        <sc-grid id="gridPanel"
                 data-provider="{{resultList}}"
                 class="flex"
                 editable="false"
                 use-selection="false"
                 use-state="false"
                 show-tooltip="true"
                 row-style-function="onRowStyle"
                 on-item-click="onItemClick">
            
            <sc-grid-columns>
                <sc-combobox-column
                                header-text="전송방법"
                                data-field="snd_cls"                width="60"              text-align="center"
                                display-field="label"               value-field="data"      items="{{codes.snd_cls}}"
                                visible="false"></sc-combobox-column>
                <sc-data-column header-text="제목"
                                data-field="mail_tit"               width="200"             text-align="left"
                                show-default-content-tooltip="true"></sc-data-column>
                <sc-image-column
                                header-text="내용"
                                data-field="btn_more"               width="40"
                                image-cls="link"></sc-image-column>
                <sc-data-column header-text="발신자주소"
                                data-field="from_addr"              width="180"             text-align="left"></sc-data-column>
                <sc-combobox-column
                                header-text="수신구분"
                                data-field="to_type"                width="80"              text-align="center"
                                display-field="label"               value-field="data"      items="{{codes.C011}}"></sc-combobox-column>
                <sc-data-column header-text="수신자주소"
                                data-field="to_addr"                width="180"             text-align="left"></sc-data-column>
                <sc-date-column header-text="등록일시"
                                data-field="reg_dt"                 width="130"             text-align="center"
                                format-type="datetime"></sc-date-column>
                <sc-date-column header-text="전송일시"
                                data-field="snd_dt"                 width="130"             text-align="center"
                                format-type="datetime"></sc-date-column>
                <sc-combobox-column
                                header-text="전송여부"
                                data-field="snd_yn"                 width="60"              text-align="center"
                                display-field="label"               value-field="data"      items="{{codes.snd_yn}}"></sc-combobox-column>
                
            </sc-grid-columns>
            <sc-grid-fields>
                <sc-grid-field data-field="bgcolor"></sc-grid-field>
            </sc-grid-fields>
        </sc-grid>


    </template>

    <script>
        Polymer({
            is: "es-mail-history",


            properties: {

                codes: {
                    type: Object,
                    reset: false,
                    value: function() {
                        return {
                            snd_yn: [],
                            snd_cls: [],
                            C011: []
                        };
                    }
                },

                // 조회 조건
                searchParam: {
                    type: Object,
                    value: function() {
                        return {};
                    }
                },

                // 조회 결과
                resultList: {
                    type: Array,
                    value: function() {
                        return [];
                    }
                }
            },

            formulas : {
                // 신규 상태
                isNew: function() {
                    return this.mailInfo.isNew === true;
                },

                // 수정 가능 상태
                isEditable : function() {
                    return !UT.isEmpty(this.searchParam.mail_set_id);
                }
            },

            /******************************
             * 초기화 설정
             ******************************/
            load: function (data) {
                var me = this;
                me.set("searchParam.mail_set_id", data.mail_set_id);
                me.onSearch();
            },

            /******************************
             * 버튼 이벤트
             ******************************/
            // 조회
            onSearch: function () {
                var me = this;

                if (!me.formula('isEditable')) {
                    UT.alert(me.translate("STD.E1012",null,me.translate('메일아이디')),null,true); //"'{0}'을(를) 선택하십시오"
                    return;
                }
                
                if (!me.validate()) {
                    // 유효하지 않은 입력값이 있습니다. 오류 정보를 확인해 주세요.
                    UT.alert("STD.E0000");
                    return;
                }

                UT.request(me.$.findListHistory);

            },
            
            onResponse : function(event)
            {
                var me = this;
                var _result = event.target.lastResponse;
                
                switch (event.target.id)
                {
                    case "findListHistory" :
                        var _resultList = _result;
                        
                        _resultList.forEach(function(data, index, array)
                        {
                            if (index > 0)
                            {
                                var _data = _resultList[index - 1];
                                
                                if (_data.mail_grp_id == data.mail_grp_id)
                                {
                                    data.bgcolor = _data.bgcolor;
                                }
                                else
                                {
                                    data.bgcolor = UT.isEmpty(_data.bgcolor) ? "#EEEEEE" : null;
                                }
                            }
                        });
                        
                        me.set("resultList", _resultList);
                        break;
                }
            },
            
            onRowStyle : function(data)
            {
                return {background:data.bgcolor};
            },
            
            onItemClick : function(event)
            {
                var me = this;
                var data = event.detail.data;
                var item = event.detail.item;
                var provider = event.detail.provider;
                
                switch (item.dataField)
                {
                    case "btn_more" :
                        var popupEpHtmlView = UT.popup("ep-html-view", me, 1000, 800, {}, {titleText:"내용보기"});
                        popupEpHtmlView.show();
                        popupEpHtmlView.getWindowContent().load({html_cont:data.mail_cont});
                        break;
                }
            },
        });
    </script>
</dom-module>

 

ep-tmp-preview.html

<dom-module id="ep-tmp-preview">

    <style>
        :host {
            @apply(--vbox-layout);
        }
    </style>

    <template>

        <!-- 상세정보 조회 -->
        <sc-ajax id="findTemplatePreview"
                 url="findTemplatePreview.do"
                 body="{{findInfo.param}}"
                 last-response="{{findInfo.result}}"
                 on-response="completeFindInfo">
        </sc-ajax>

		<cc-sub-title-bar title-text="템플릿미리보기">
		</cc-sub-title-bar>
		
        <sc-editor id="editor" class="flex" value="{{findInfo.result.previewHtml}}" editable="false"></sc-editor>
    </template>

    <script>
        Polymer({
            is: "ep-tmp-preview",
            properties: {
                findInfo: {
                    type: Object,
                    value: function() {
                        return {
                            param: {},
                            result: {}
                        };
                    }
                }
            },

            // 화면 생성 완료
            initialized: function() {
                var me = this;

                me.fire("attached");
            },

            // 기본 파라미터 설정
            load: function(options) {
                var me = this;
                options = options || {};

                if (UT.isObject(options.defaultParam)) {
                    me.set("findInfo.param", options.defaultParam);
                    
                    // 템플릿 값이 있는 경우(템플릿 과 내용을 합쳐서 보여줌)
                    if(options.defaultParam.tmp_bas_id){
                    	me.onFindInfo();
                    	
                    // 템플릿 값이 없는 경우(내용만 보여줌)
                    }else{
                    	me.set("findInfo.result.previewHtml", options.defaultParam.contents);
                    }
                    
                }
            },

            // 상세정보 조회
            onFindInfo: function() {
                var me = this;

                UT.request(me.$.findTemplatePreview);
            },

            // 상세정보 조회 완료
            completeFindInfo: function(e, res) {
            	var me = this;
            	
            	var result = res.response;
            	
            	if(result){
            		me.set("findInfo.result.previewHtml", result.previewHtml);
            	}
            	
            }

        });
    </script>

</dom-module>

 

ep-mail-send-test.html

<sc-link href="../../../lib/jsoneditor/dist/jsoneditor.min.css" rel="stylesheet" type="text/css"></sc-link>
<script src="../../../lib/jsoneditor/dist/jsoneditor.min.js"></script>

<dom-module id="ep-mail-send-test">
    <style>
        :host {
            @apply(--vbox-layout);
        }
    </style>

    <template>
        <sc-code-group>
            <sc-code code="C011" value="{{codes.C011}}"></sc-code>  <!-- 메일수신구분 -->
        </sc-code-group>
        
        <!-- SMTP 연동 테스트를 위한 Ajax -->
        <sc-ajax id="sendTestMail"
                 url="sendTestMail.do">
        </sc-ajax>

        <cc-auth-checker check-list="auth-r, auth-s"></cc-auth-checker>
        
        <cc-sub-title-bar>
            <sc-button auth-r id="btnSnd" on-click="onBtnClick" text="테스트메일전송"></sc-button>
        </cc-sub-title-bar>
        
        <table class="tb-form">
            <colgroup>
                <col width="120">
                <col>
            </colgroup>
            <tr>
                <th><sc-label text="메일아이디"></sc-label></th>
                <td><sc-text-field value="{{testMailInfo.mailKey}}" disabled="true"></sc-text-field></td>
            </tr>
            <tr>
                <th><sc-label text="발신자이름"></sc-label></th>
                <td><sc-text-field value="{{testMailInfo.from_nm}}" required="true"></sc-text-field></td>
            </tr>
            <tr>
                <th><sc-label text="발신자메일주소"></sc-label></th>
                <td><sc-text-field value="{{testMailInfo.from_addr}}" required="true" max-length="200" mask-re="/[A-Za-z0-9-_.@]/" strip-chars-re="/[ㄱ-힣]/" validator-type="email"></sc-text-field></td>
            </tr>
        </table>
        
        <sc-grid id="gridPanel"
                 data-provider="{{resultList}}"
                 class="h-200"
                 editable="true"
                 use-state="true"
                 use-selection="true"
                 on-item-click="onItemClick">
                 
            <cc-grid-toolbar title-text="수신자">
                <sc-button auth-r id="btnAdd" on-click="onBtnClick" text="추가"></sc-button>
                <sc-button auth-r id="btnDel" on-click="onBtnClick" text="삭제"></sc-button>
            </cc-grid-toolbar>
            
            <sc-grid-columns>
                <sc-combobox-column
                                header-text="수신구분"
                                data-field="to_type"                    width="80"                  text-align="center"
                                display-field="label"                   value-field="data"          items="{{codes.C011}}"
                                required="true"                         editable="true">
                </sc-combobox-column>
                <sc-data-column header-text="담당자"
                                data-field="to_nm"                      width="150"                 text-align="left"
                                required="true"                         editable="true"
                                max-length="50">
                </sc-data-column>
                <sc-data-column header-text="이메일"
                                data-field="to_addr"                    width="250"                 text-align="left"
                                required="true"                         editable="true"
                                max-length="50"                         validator-type="email">
                </sc-data-column>
            </sc-grid-columns>
        </sc-grid>
        
        <sc-panel title-text="Data입력" class="flex">
            <div>템플릿과 데이터의 결합은 FreeMarker템플릿 엔진을 사용합니다.</div>
            <cc-sub-title-bar>
                <sc-button text="Data Reset" on-click="onClickDataReset" i18n-disabled></sc-button>
            </cc-sub-title-bar>
            <div id="jsonEditor" style="height:350px;"></div>
        </sc-panel>
        
        <sc-upload id="attFile" class="h-150" value="{{testMailInfo.grp_cd}}"></sc-upload>
    </template>

	<script>
        Polymer({
            is: 'ep-mail-send-test',

            properties:{
                codes : {
                    type : Object,
                    value : function() {
                        return {
                            C011 : [],
                        }
                    },
                    reset : false
                },
                testMailInfo: {
                    type: Object,
					value: function () {
						return {
							from_nm  : "KEPCO E&C P-manager",
							from_addr : "kepco-enc@kepco-enc.com",
							data: {}
						};
                    }
				},
                resultList: {
                    type: Array,
                    value: function() {
                        return [];
                    }
                },
				titleText: {
                    type: String,
					value: "테스트메일전송"
				}
            },

			initialized: function () {
                var me = this;

                /** JSON Data Load **/
                if(window.jsoneditor && window.jsoneditor.JSONEditor){
                    jsonEditor = window.jsoneditor.JSONEditor;
                }else if(window.JSONEditor){
                    if(window.JSONEditor.JSONEditor){
                        jsonEditor = window.JSONEditor.JSONEditor;
                    }else{
                        jsonEditor = window.JSONEditor;
                    }
                }

                var options = {};
                me.jsonEditor = new jsonEditor(me.$.jsonEditor, options);
            },

            load: function(mailKey, getEditorValueFn){
                var me = this;

                me.set("testMailInfo.mailKey", mailKey);

                me.set("resultList", [{to_type:"TO"},{to_type:"CC"},{to_type:"BCC"}]);
                
                me.setDefaultJsonEditorData(getEditorValueFn());
            },
            
            onClickDataReset: function() {
            	var me = this;
            	me.setDefaultJsonEditorData();
            },

          	//Default Json Data Setting
			setDefaultJsonEditorData: function (editorValue) {
                var me = this;
                me.editorValue = editorValue || me.editorValue || "";
                var matched = me.editorValue.match(/\${[a-zA-Z0-9_.]{1,}/g);

                var obj = {};
                if(matched && matched.length) {
                	for(var i=0,len=matched.length; i<len; i++) {
                		var prop = (matched[i] || "").replace("${", "");
                		dotToObj(obj, prop);
                	}
                }
                
                me.jsonEditor.set({ //data 라는 property에 기본값이 들어감
                    data: obj
                });
                
                /* 
                input -> 1.2.3
                output -> {1: {2: {3: ""}}}
                */
                function dotToObj(obj, str) {

                	var split = str.split(".");
                	if(split.length > 1) {
                		obj[split[0]] = obj[split[0]] || {};
                		dotToObj(obj[split[0]], split.slice(1).join("."));
                	} else {
                		obj[str] = obj[str] || "";
                    }
                	return obj;
                }
            },

            onBtnClick : function(event)
            {
                var me = this;
                
                me._btn         = event.target;
                var _btnLabel   = me.translate(me._btn.text);
                var _isCtrl     = event.ctrlKey;
                
                switch (event.target.id)
                {
                    case "btnAdd" :
                        var _provider = me.$.gridPanel.getDataProvider();
                        
                        var _newRow     = {};
                        _newRow.to_type = null;
                        _newRow.to_addr = null;
                        _newRow.to_nm   = null;
                        _provider.addItem(_newRow);
                        break;
                        
                    case "btnDel" :
                        var _provider = me.$.gridPanel.getDataProvider();
                        var _checkedIndexes = _provider.selectionCheckedIndexes();
                        
                        if (_checkedIndexes.length == 0)
                        {
                            // 선택된 항목이 없습니다.
                            UT.alert("STD.N1600");
                            return;
                        }

                        // 삭제 하시겠습니까?
                        UT.confirm("STD.N1300", function()
                        {
                            _provider.removeItemsByIndexes(_checkedIndexes);
                        });
                        break;
                        
                    case "btnSnd" :
                        var _provider = me.$.gridPanel.getDataProvider();
                        
                        if (!me.validate())
                        {
                            // 유효하지 않은 입력값이 있습니다. 오류 정보를 확인해 주세요.
                            UT.alert("STD.E0000");
                            return;
                        }

                        if (_provider.getItems().length == 0)
                        {
                            // '{0}'은(는) 필수 입력 항목입니다.
                            UT.alert(me.translate("STD.E1001", null, me.translate("수신자")), null, true);
                            return;
                        }
                        
                        //JSONEditor 에서 설정한 값을 불러와서 파라미터(data)에 넣어줌
                        me.testMailInfo.data = me.jsonEditor.get().data;

                        // {0}을(를) 하시겠습니까?
                        UT.confirm(me.translate("STD.COM1003", null, _btnLabel), function()
                        {
                            Promise.all([me.$.attFile.upload()]).then(function()
                            {
                                var _param      = me.testMailInfo;
                                _param.to_list  = _provider.getItems();
                                
                                me.$.sendTestMail.body = _param;
                                UT.request(me.$.sendTestMail, function(event)
                                {
                                    var _result = event.target.lastResponse;
                                    
                                    //console.log(_result);
                                    
                                    UT.alert("메일발송을완료했습니다. 메일 전송은 비동기로 전송되기 때문에 실패해도 화면에 에러메시지를 표시하지 않습니다.", null, true);
                                });
                            });
                        }, null, true);
                        break;

                }
            },
        });
	</script>

</dom-module>

 

ep-html-view.html

<dom-module id="ep-html-view">
    <style>
        :host {
            @apply(--vbox-layout);
        }
    </style>

    <template>
        <cc-source-editor id="editor" class="flex" value="{{searchParam.html_cont}}" editable="true" mode-disabled="true"></cc-source-editor>
    </template>

    <script>
        Polymer({
            is: "ep-html-view",
            properties: {
                searchParam : {
                    type : Object,
                    value : function() {
                        return {};
                    }
                },
                titleText: {
                    type: String,
                    value: function() {
                        return "내용보기";
                    }
                }
            },

            // 화면 생성 완료
            initialized: function()
            {
                var me = this;
            },

            // 기본 파라미터 설정
            load: function(param)
            {
                var me = this;
                
                me.set("searchParam.html_cont", param.html_cont || "");
                
                me.$.editor.$.tabNavi.selectedIndex = 1;
            },
        });
    </script>
</dom-module>

 

MailController.java

package smartsuite.app.bp.admin.mail;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import smartsuite.app.bp.admin.mailWork.MailWorkService;
import smartsuite.app.common.shared.Const;
import smartsuite.security.annotation.AuthCheck;

import javax.inject.Inject;
import java.util.List;
import java.util.Map;

@SuppressWarnings ({ "rawtypes", "unchecked" })
@Controller
@RequestMapping(value="**/bp/**/")
public class MailController {

	@Inject
    MailService mailService;

	@Inject
    MailWorkService mailWorkService;

	/* 메일 목록 조회 */
	@AuthCheck(authCode = Const.READ)
	@RequestMapping(value="findListMail.do")
	public @ResponseBody
    List findListMail(@RequestBody Map param){
		return mailService.findListMail(param);
	}
	
	
	/* 메일 목록 상세 조회(단건조회) */
	@AuthCheck(authCode = Const.READ)
	@RequestMapping(value="findListMailByMailId.do")
	public @ResponseBody
    Map findListMailByMailId(@RequestBody Map param){
		return mailService.findListMailByMailId(param);
	}
	
	/* 삭제 */
	@AuthCheck(authCode = Const.SAVE)
	@RequestMapping(value="deleteListMail.do")
	public @ResponseBody
    Map deleteListMail(@RequestBody Map param){
		return mailService.deleteListMail(param);
	}
	
	/* 저장 */
	@AuthCheck(authCode = Const.SAVE)
	@RequestMapping(value="saveListMail.do")
	public @ResponseBody
    Map saveListMail(@RequestBody Map param){
		return mailService.saveListMail(param);
	}
	
	/* combobox 목록조회 */
	@AuthCheck(authCode = Const.READ)
	@RequestMapping(value="getAllTmpBasIdList.do")
	public @ResponseBody
    List getAllTmpBasIdLis(@RequestBody Map param){
		return mailService.getAllTmpBasId(param);
	}
	
	/* 메일전송이력 조회 */
	@AuthCheck(authCode = Const.READ)
	@RequestMapping(value="findListHistory.do")
	public @ResponseBody
    List findListHistory(@RequestBody Map param){
		return mailService.findListHistory(param);
	}
	
	/* 다중메일 전송 이력 조회 */
	@AuthCheck(authCode = Const.READ)
	@RequestMapping(value="findMultiMailSendHistory.do")
	public @ResponseBody
    List findMultiMailSendHistory(@RequestBody Map param){
		return mailService.findMultiMailSendHistory(param);
	}

	/* SMTP 연동 테스트  */
	@AuthCheck(authCode = Const.SAVE)
	@RequestMapping(value="sendTestMail.do")
	public @ResponseBody
    Map sendTestMail(@RequestBody Map param){
		return mailService.sendTestMail(param);
	}
}

 

MailService.java

package smartsuite.app.bp.admin.mail;

import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import smartsuite.app.common.mail.CommonMailService;
import smartsuite.exception.CommonException;
import smartsuite.exception.ErrorCode;

import javax.inject.Inject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
@Transactional
@SuppressWarnings ({ "rawtypes", "unchecked" })
public class MailService {

	@Inject
	private SqlSession sqlSession;
	
	@Inject
	private CommonMailService commonMailService;
	
	/*NAMESPACE*/
	private static final String NAMESPACE = "mail.";
	
	/* 메일 목록 조회 */
	public List<Map<String, Object>> findListMail(Map<String, Object> param) {
		return sqlSession.selectList(NAMESPACE + "findListMail", param);
	}
	
	/* 메일 목록 상세 조회 */
	public Map findListMailByMailId(Map param) {
		Map<String,Object> mailInfo;
		
		mailInfo = sqlSession.selectOne(NAMESPACE + "findListMailByMailId", param);
		
		return mailInfo;
	}
	
	/* 메일 목록 삭제 */
	public Map deleteListMail(Map<String, Object> param) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		List <Map<String, Object>> deletes = (List<Map<String, Object>>)param.get("deleteMail");
		
		for(Map<String, Object> row : deletes){
			this.deleteMail(row);
		}
		
		return resultMap;
	}
	
	/* 메일 삭제 */
	public void deleteMail(Map<String, Object> param){
		//유효성체크
		Map<String,Object> invalidMailSetInfo = sqlSession.selectOne(NAMESPACE+"findContent", param);
		String tmpId=(String) invalidMailSetInfo.get("tmp_id");
		
		Integer countMailHistory = sqlSession.selectOne(NAMESPACE+"findCountMailHistory",param);
		if(invalidMailSetInfo != null){
			if(countMailHistory > 0){
				sqlSession.update(NAMESPACE+"updateStsDMailSetup",param);
				param.put("tmp_id", tmpId);
				sqlSession.update(NAMESPACE+"updateStsDMailTmpContent", param);
			}else{
				sqlSession.delete(NAMESPACE+"deleteMail", param);
				
				param.put("tmp_id", tmpId);
				sqlSession.delete(NAMESPACE+"deleteContent", param);
			}
		}

	}

	/* 저장 */
	public Map<String, Object> saveListMail(Map<String, Object> param) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		Map<String, Object> info = param;
		
		boolean isNew = false;
		
		if(info.get("isNew")!=null){
			isNew = (Boolean)info.get("isNew");
		}
		
		// 신규 저장
		if(isNew){
			boolean exist = false;
			
			if(info != null && !info.isEmpty() && this.getCountMail(info) > 0){
				exist = true;
			}
			if(exist){
				// 중복
				throw new CommonException(ErrorCode.DUPLICATED);
			}
			
			if(info!= null && !info.isEmpty()){
				// 메일 정보, 템플릿 본문 insert
				info.put("tmp_id", UUID.randomUUID().toString());
				sqlSession.insert(NAMESPACE + "insertContent", info);
				sqlSession.insert(NAMESPACE + "insertMail", info);
			}
		}
		else{
			if (info != null && !info.isEmpty()) {
				// 메일 정보, 템플릿 본문 update
				sqlSession.update(NAMESPACE + "updateMail", info);
				sqlSession.update(NAMESPACE + "updateContent", info);
			}
			
		}
		return resultMap;
	}
	
	private int getCountMail(Map<String, Object> param) {
		return sqlSession.selectOne(NAMESPACE + "getCountMail", param);
	
	}

	public List getAllTmpBasId(Map<String, Object> param) {
		return sqlSession.selectList(NAMESPACE+"getAllTmpBasIdList", param);
	}

	/* 전송이력 조회 */
	public  List<Map<String, Object>> findListHistory(Map<String, Object> param) {
		return sqlSession.selectList(NAMESPACE + "findListHistory", param);
	}

	/* SMTP 연동 테스트  */
	public Map sendTestMail(Map param) {
		commonMailService.addMail((String) param.get("mailKey"), param);
		
		return param;
	}

	/* 다중메일 전송 이력 조회 */
	public  List<Map<String, Object>> findMultiMailSendHistory(Map<String, Object> param) {
		return sqlSession.selectList(NAMESPACE + "findMultiMailSendHistory", param);
	}
}

 

mail.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mail">
	
	<resultMap type="map" id="resultMap-findInfoMail">
        <result property="tmp_cont" column="TMP_CONT" jdbcType="CLOB" javaType="string" />
    </resultMap>
	<select id="findListMail" resultMap="resultMap-findInfoMail">
		/* mail.findListMail : 메일 목록 조회*/
        SELECT  ML.SYS_ID
        ,       ML.MAIL_SET_ID
        ,       ML.MAIL_SET_NM
        ,       MT.MOD_DT
        
        ,       TM.TMP_BAS_ID
        ,       TM.TMP_BAS_NM
        
        ,       (SELECT MAX(SND_DT)
                FROM ESAMAIL L
                WHERE L.SYS_ID      = ML.SYS_ID
                AND L.MAIL_SET_ID   = ML.MAIL_SET_ID)   AS SND_DT
        
        FROM ESACFML ML
        JOIN ESATMPM MT ON  MT.SYS_ID       = ML.SYS_ID
                        AND MT.TMP_ID       = ML.TMP_ID 
        
        JOIN ESATMPB TM ON  TM.SYS_ID       = MT.SYS_ID
                        AND TM.TMP_CLS      = MT.TMP_CLS
                        AND TM.TMP_BAS_ID   = MT.TMP_BAS_ID
        
        WHERE ML.SYS_ID = #{g.tenant}
        AND ML.STS != 'D'
        
        ORDER BY    TM.TMP_BAS_ID
        ,           ML.MAIL_SET_ID
	</select>
	
	<resultMap type="map" id="resultMap-findInfoMailById">
        <result property="tmp_cont" column="TMP_CONT" jdbcType="CLOB" javaType="string" />
    </resultMap>
    <select id="findListMailByMailId" resultMap="resultMap-findInfoMailById">
        /* mail.findListMailByMailId : 메일 목록 상세 조회*/
        SELECT  ML.SYS_ID
        ,       ML.MAIL_SET_ID
        ,       ML.MAIL_SET_NM
        ,       ML.USE_YN
        ,       ML.SND_CLS
        
        ,       MT.TMP_ID
        ,       MT.TMP_CLS
        ,       MT.TMP_BAS_ID
        ,       MT.TMP_NM
        ,       MT.TMP_CONT
        ,       MT.PARAM_CLASS_NM
        ,       MT.MOD_DT
        
        FROM ESACFML ML
        JOIN ESATMPM MT ON  MT.SYS_ID       = ML.SYS_ID
                        AND MT.TMP_ID       = ML.TMP_ID 
                        
        WHERE ML.SYS_ID     = #{g.tenant}
        AND ML.MAIL_SET_ID  = #{p.mail_set_id}
        AND ML.STS != 'D'
    </select>
	
	<!-- 저장 -->
	<insert id="insertContent">
		/* mail.saveListMail  템플릿 본문 신규저장 */
		INSERT INTO ESATMPM(
			SYS_ID
			, TMP_ID
			, TMP_CLS
			, TMP_BAS_ID
			, TMP_NM
			, TMP_CONT
			, PARAM_CLASS_NM
			, STS
			, REG_ID
			, REG_DT
			, MOD_ID
			, MOD_DT
		)
		VALUES(
			#{g.tenant}
			,#{p.tmp_id}
			,(SELECT TMP_CLS FROM ESATMPB WHERE ESATMPB.TMP_BAS_ID = #{p.tmp_bas_id} AND ESATMPB.SYS_ID = #{g.tenant})
			,#{p.tmp_bas_id}
			,#{p.tmp_nm}
			,#{p.tmp_cont}
			,#{p.param_class_nm}
			,'C'
			,#{g.username}
			,#{g.now}
			,#{g.username}
			,#{g.now}
		)
			
	</insert>
	<insert id="insertMail">
		/* mail.saveListMail 메일 설정 신규저장*/
		INSERT INTO ESACFML(
			SYS_ID
			, MAIL_SET_ID
			, MAIL_SET_NM
			, TMP_ID
			, USE_YN
			, SND_CLS
			, STS
			, REG_ID
			, REG_DT
			, MOD_ID
			, MOD_DT
		)
		VALUES(
			#{g.tenant}
			,#{p.mail_set_id}
			,#{p.mail_set_nm}
			 ,#{p.tmp_id}
			,#{p.use_yn}
			,#{p.snd_cls}
			,'C'
			,#{g.username}
			,#{g.now}
			,#{g.username}
			,#{g.now}
		)
	</insert>
	
	<update id="updateMail">
		/*mail.saveListMail 메일 설정 수정*/
		UPDATE ESACFML
			SET STS='U'
				, MOD_ID = #{g.username}
				, MOD_DT = #{g.now}
					, MAIL_SET_ID = #{p.mail_set_id}
					, MAIL_SET_NM = #{p.mail_set_nm}
					, USE_YN = #{p.use_yn}
					, SND_CLS = #{p.snd_cls}
			WHERE SYS_ID = #{g.tenant}
		 		AND MAIL_SET_ID = #{p.mail_set_id}
	</update>
	
	<update id="updateContent">
		/*mail.saveListMail 템플릿 본문 수정*/
		UPDATE ESATMPM
			SET STS='U'
				, MOD_ID = #{g.username}
				, MOD_DT = #{g.now}
				
				<if test='p.param_class_nm != null' >
					, PARAM_CLASS_NM = #{p.param_class_nm}	
				</if>
				<if test='p.tmp_bas_id != null' >
					, TMP_BAS_ID = #{p.tmp_bas_id}	
				</if>
				<if test='p.tmp_cont != null' >
					, TMP_CONT = #{p.tmp_cont}	
				</if>
			 WHERE SYS_ID = #{g.tenant}
		 		AND TMP_ID = #{p.tmp_id}
	</update>
	
	<select id="getCountMail" resultType="int">
		SELECT COUNT(*)
    	  FROM ESATMPM
    	 WHERE SYS_ID = #{g.tenant}
     		  AND TMP_ID = #{p.tmp_id}
	</select>
	
	<select id="findCountMailHistory" resultType="int">
		/* mail.findCountMailHistory */
		SELECT COUNT(MAIL_ID) AS CNT
		FROM ESAMAIL
		WHERE SYS_ID = #{g.tenant}
		AND MAIL_SET_ID = #{p.mail_set_id}
	</select>
	
	<update id="updateStsDMailSetup">
		/* mail.updateStsDMailSetup: ESACFML 메일설정 삭제 상태로 변경 */
		UPDATE ESACFML
			SET STS='D' 
			WHERE SYS_ID= #{g.tenant}
				AND MAIL_SET_ID = #{p.mail_set_id}
	</update>
	
	<update id="updateStsDMailTmpContent">
		/* mail.updateStsDMailTmpContent: ESATMPM 템플릿 본문 삭제 상태로 변경 */
		UPDATE ESATMPM
			SET STS='D'
			WHERE SYS_ID= #{g.tenant}
				AND TMP_ID =#{p.tmp_id}
	</update>
	
	<delete id="deleteMail">
		/* mail.deleteMail: ESACFML 메일설정 삭제 */
		DELETE FROM ESACFML
			WHERE SYS_ID= #{g.tenant}
				AND MAIL_SET_ID = #{p.mail_set_id}
	</delete>
	
	<delete id="deleteContent">
		/* mail.deleteContent: ESATMPM 템플릿 본문 삭제 */
		DELETE FROM ESATMPM
			WHERE SYS_ID= #{g.tenant}
				AND TMP_ID =#{p.tmp_id}
	</delete>
	
	
	<select id="getAllTmpBasIdList" resultType="map">
		/*콤보박스 select*/
		SELECT TMP_BAS_ID
			, TMP_BAS_NM
			
    	  FROM ESATMPB
    	 WHERE SYS_ID = #{g.tenant}
    	 	AND TMP_CLS = 'TM'
    	 	
	</select>
	
	<resultMap type="map" id="resultMap-findListHistory">
        <result property="mail_cont" column="MAIL_CONT" jdbcType="CLOB" javaType="string" />
    </resultMap>
	<select id="findListHistory" resultMap="resultMap-findListHistory">
		/* mail.findListHistory 메일전송이력 조회 */
        SELECT  B.SYS_ID
        ,       B.MAIL_ID
        ,       B.MAIL_SET_ID
        ,       B.MAIL_GRP_ID
        ,       B.MAIL_TIT
        ,       B.MAIL_CONT
        ,       B.FROM_ADDR
        ,       B.FROM_NM
        ,       B.TO_ADDR
        ,       B.TO_NM
        ,       B.TO_TYPE
        ,       B.SND_YN
        ,       B.SND_DT
        ,       B.REG_ID
        ,       B.REG_DT
        
        ,       A.SND_CLS
        
        FROM ESACFML A
        JOIN ESAMAIL B  ON  B.SYS_ID        = A.SYS_ID 
                        AND B.MAIL_SET_ID   = A.MAIL_SET_ID
                    <if test="p.from_date != null">
                        AND NVL(B.SND_DT, #{g.now}) <![CDATA[>=]]> #{p.from_date}
                    </if>
                    <if test="p.to_date != null">
                    <bind name="to_date" value="g.getPlusDays(p.to_date, 1)"/>
                        AND NVL(B.SND_DT, #{g.now}) <![CDATA[<]]>  #{to_date}
                    </if>
            
        WHERE A.SYS_ID      = #{g.tenant}
        AND A.MAIL_SET_ID   = #{p.mail_set_id}
        AND A.STS          != 'D'
        
        ORDER BY B.REG_DT DESC, B.SND_DT DESC NULLS LAST
	</select>
	
	<!-- 메일설정(ESACFML) 테이블에서 TMP_ID select -->
	<select id="findContent" resultType="map">
		SELECT A.TMP_ID FROM ESACFML A
			WHERE A.SYS_ID= #{g.tenant}
				AND A.MAIL_SET_ID = #{p.mail_set_id}
	</select>
	
	<insert id="insertEsamail">
		INSERT INTO ESAMAIL (
      			SYS_ID
      			,MAIL_ID					/*메일 아이디 */
      			,MAIL_SET_ID				/*메일 설정 아이디 */
                ,MAIL_GRP_ID                /*메일 단위 아이디 */
      			,MAIL_TIT					/*메일 제목*/
      			,MAIL_CONT					/*메일 내용*/
      			,TO_NM						/*송신자 이름*/
      			,TO_ADDR					/*송신자 주소*/
      			,FROM_NM					/*수신자 이름*/
      			,FROM_ADDR					/*수신자 주소*/
                ,TO_TYPE                    /*수신 구분*/
                ,SND_YN                     /*전송 여부*/
                ,SND_DT                     /*전송 일시*/
                ,REG_ID
                ,REG_DT
                )
        VALUES  (
      			#{g.tenant}
      			, #{p.mail_id}
      			, #{p.mail_set_id}
                , #{p.mail_grp_id}
      			, #{p.mail_tit}
      			, #{p.mail_cont}
      			, #{p.to_nm}
      			, #{p.to_addr}
      			, #{p.from_nm}
      			, #{p.from_addr}
                , #{p.to_type}
                , #{p.snd_yn}
                , #{p.snd_dt}
                , NVL(#{g.username}, 'SYSTEM')
                , #{g.now}
                )
	</insert>

	<!-- 보내지 않은 메일 (ESAMAIL) 목록 조회  -->
	<resultMap type="map" id="resultMap-findListSendMail">
        <result property="mail_cont" column="MAIL_CONT" jdbcType="CLOB" javaType="string" />
    </resultMap>
	<select id="findListSendMail" resultMap="resultMap-findListSendMail">
		/* commonCode.findListSendMail */
        
        SELECT  SYS_ID                                  AS SYS_ID                               -- PK(1) 시스템 아이디 ESAMAIL_ESACFML_FK(1)
        ,       MAIL_ID                                 AS MAIL_ID                              -- PK(2) 메일 아이디 
        ,       MAIL_SET_ID                             AS MAIL_SET_ID                          -- 메일 설정 아이디 ESAMAIL_ESACFML_FK(2)
        ,       MAIL_GRP_ID                             AS MAIL_GRP_ID                          -- 메일 단위 아이디 
        ,       MAIL_TIT                                AS MAIL_TIT                             -- 메일 제목 
        ,       MAIL_CONT                               AS MAIL_CONT                            -- 메일 내용 
        ,       FROM_ADDR                               AS FROM_ADDR                            -- FROM 주소 
        ,       FROM_NM                                 AS FROM_NM                              -- FROM 명 
        ,       TO_ADDR                                 AS TO_ADDR                              -- TO 주소 
        ,       TO_NM                                   AS TO_NM                                -- TO 명 
        ,       TO_TYPE                                 AS TO_TYPE                              -- 수신 구분 [TO/CC/BCC] 
        ,       SND_YN                                  AS SND_YN                               -- 전송 여부 [Y/N] 
        ,       SND_DT                                  AS SND_DT                               -- 전송 일시 
        ,       REG_ID                                  AS REG_ID                               -- 등록자 아이디 
        ,       REG_DT                                  AS REG_DT                               -- 등록 일시 

        FROM ESAMAIL
        WHERE SYS_ID = #{g.tenant}
        AND SND_YN = 'N'
	</select>
	
    <resultMap type="map" id="resultMap-findESAMailById">
        <result property="tmp_cont" column="TMP_CONT" jdbcType="CLOB" javaType="string" />
    </resultMap>
    <select id="findESAMailById" resultMap="resultMap-findESAMailById">
        /* mail.findESAMailById : 메일 목록 상세 조회*/
        
        SELECT  SYS_ID                                  AS SYS_ID                               -- PK(1) 시스템 아이디 ESAMAIL_ESACFML_FK(1)
        ,       MAIL_ID                                 AS MAIL_ID                              -- PK(2) 메일 아이디 
        ,       MAIL_SET_ID                             AS MAIL_SET_ID                          -- 메일 설정 아이디 ESAMAIL_ESACFML_FK(2)
        ,       MAIL_GRP_ID                             AS MAIL_GRP_ID                          -- 메일 단위 아이디 
        ,       MAIL_TIT                                AS MAIL_TIT                             -- 메일 제목 
        ,       MAIL_CONT                               AS MAIL_CONT                            -- 메일 내용 
        ,       FROM_ADDR                               AS FROM_ADDR                            -- FROM 주소 
        ,       FROM_NM                                 AS FROM_NM                              -- FROM 명 
        ,       TO_ADDR                                 AS TO_ADDR                              -- TO 주소 
        ,       TO_NM                                   AS TO_NM                                -- TO 명 
        ,       TO_TYPE                                 AS TO_TYPE                              -- 수신 구분 [TO/CC/BCC] 
        ,       SND_YN                                  AS SND_YN                               -- 전송 여부 [Y/N] 
        ,       SND_DT                                  AS SND_DT                               -- 전송 일시 
        ,       REG_ID                                  AS REG_ID                               -- 등록자 아이디 
        ,       REG_DT                                  AS REG_DT                               -- 등록 일시 

        FROM ESAMAIL
        WHERE SYS_ID    = #{g.tenant}
        AND MAIL_GRP_ID = #{p.mail_grp_id}
	</select>

    <!-- 전송여부 변경  -->
    <update id="updateSendComplete">
        /* mail.updateSendComplete : 메일 전송 여부 업데이트*/
        
        UPDATE ESAMAIL
           SET SND_YN = #{p.snd_yn}
             , SND_DT = DECODE(#{p.snd_yn}, 'Y', #{g.now}, 'N', NULL)
        
        WHERE SYS_ID = #{g.tenant}

        <choose>
            <when test="@org.apache.commons.collections4.CollectionUtils@isNotEmpty(p.mail_ids)">
        AND MAIL_ID IN
                <foreach collection="p.mail_ids" item="mail_id" open="(" close=")" separator=",">
                    #{mail_id}
                </foreach>
            </when>
            <otherwise>
        AND 1 = 0
            </otherwise>
        </choose>
    </update>
    
	<!-- 신규 개발 -->
	<select id="findESAMail" resultType="map">
		/* mail.findESAMail : 메일 목록 상세 조회*/
		SELECT SYS_ID
			, MAIL_ID

		FROM ESAMAIL
		WHERE 1=1
		AND MAIL_TIT LIKE '%'|| #{p.mail_tit} ||'%'
		AND TO_ADDR = #{p.from_addr}
		ORDER BY REG_DT DESC
	</select>


	<select id="findLastRecivedMail" resultType="map">
		/* mail.findLastRecivedMail */
		SELECT MAX(RECEIVED_DT) SND_DT FROM ESAMWRH WHERE SYS_ID= #{g.tenant}
	</select>

	<resultMap type="map" id="resultMap-findUnProcessedMails">
        <result property="mail_cont" column="MAIL_CONT" jdbcType="CLOB" javaType="string" />
    </resultMap>

	<select id="findUnProcessedMails" resultMap="resultMap-findUnProcessedMails">
		/* mail.findUnProcessedMails */
		SELECT
			 SYS_ID
			,EMAIL_RECEIVED_LOG_ID
			,EMAIL_WORK_TARG_ID
			,RECEIVED_CATE
			,RECEIVED_STS_CD
			,FROM_ADDR
			,FROM_NM
			,TO_ADDR
			,TO_NM
			,MAIL_TIT
			,MAIL_CONT
			,ATTFILE
			,RST_MSG
			,RECEIVED_DT
			,REG_ID
			,REG_DT
			,MOD_DT
			,MOD_ID
		FROM ESAMWRH WHERE 1=1
		AND RECEIVED_CATE = 'RE'
		AND RECEIVED_STS_CD = 'N'
		ORDER BY REG_DT ASC
	</select>


	<resultMap type="map" id="resultMap-findESAMTMailById">
		<result property="tmp_cont" column="TMP_CONT" jdbcType="CLOB" javaType="string" />
		<result property="bcc_addr_list" column="BCC_ADDR_LIST" jdbcType="CLOB" javaType="string" />
		<result property="bcc_nm_list" column="BCC_NM_LIST" jdbcType="CLOB" javaType="string" />
		<result property="cc_addr_list" column="CC_ADDR_LIST" jdbcType="CLOB" javaType="string" />
		<result property="cc_nm_list" column="CC_NM_LIST" jdbcType="CLOB" javaType="string" />
		<result property="to_addr_list" column="TO_ADDR_LIST" jdbcType="CLOB" javaType="string" />
		<result property="to_nm_list" column="TO_NM_LIST" jdbcType="CLOB" javaType="string" />
	</resultMap>
	<select id="findESAMTMailById" resultMap="resultMap-findESAMTMailById">
		/* mail.findESAMTMailById : 메일 목록 상세 조회*/
		SELECT A.SYS_ID
			, A.MAIL_ID
			, A.MAIL_SET_ID
			, A.MAIL_TIT
			, A.FROM_ADDR
			, A.FROM_NM
			, A.BCC_ADDR_LIST
			, A.BCC_NM_LIST
			, A.CC_ADDR_LIST
			, A.CC_NM_LIST
			, A.TO_ADDR_LIST
			, A.TO_NM_LIST
			, A.SND_DT
			, A.SND_YN
			, A.REG_ID
			, A.REG_DT
			, B.SND_CLS
		FROM ESAMTML A
	   INNER JOIN ESACFML B
          ON A.SYS_ID = B.SYS_ID
         AND A.MAIL_SET_ID = B.MAIL_SET_ID
		WHERE A.SYS_ID = #{g.tenant}
		  AND A.MAIL_ID = #{p.mail_id}
	</select>

	<!-- 다중 발송 전송여부 변경  -->
	<update id="updateMultiSendComplete">
		/* mail.updateMultiSendComplete : 다중 메일 전송 여부 업데이트*/
		UPDATE ESAMTML
			SET snd_yn = #{p.snd_yn}
				, snd_dt = #{g.now}
		WHERE SYS_ID = #{g.tenant}
		  AND mail_id = #{p.mail_id}
	</update>

	<insert id="insertEsaMtMail">
		INSERT INTO ESAMTML
		<trim prefix="(" suffix=")" prefixOverrides=",">
			SYS_ID
			,REG_ID
			,REG_DT
			,MAIL_ID					/*메일 아이디 */
			,MAIL_SET_ID				/*메일 설정 아이디 */
			<if test="p.mail_tit != null">
				,MAIL_TIT					/*메일 제목*/
			</if>
			<if test="p.mail_cont != null">
				,MAIL_CONT					/*메일 내용*/
			</if>

			<if test="p.to_nm_list != null">
				,TO_NM_LIST						/*송신자 이름 목록*/
			</if>
			<if test="p.to_addr_list != null">
				,TO_ADDR_LIST					/*송신자 주소 목록*/
			</if>
			<if test="p.cc_nm_list != null">
				,CC_NM_LIST						/*CC 송신자 이름 목록*/
			</if>
			<if test="p.cc_addr_list != null">
				,CC_ADDR_LIST					/*CC 송신자 주소 목록*/
			</if>
			<if test="p.bcc_nm_list != null">
				,BCC_NM_LIST						/* BCC 송신자 이름 목록*/
			</if>
			<if test="p.bcc_addr_list != null">
				,BCC_ADDR_LIST					/* BCC 송신자 주소 목록*/
			</if>
			<if test="p.from_nm != null">
				,FROM_NM					/*수신자 이름*/
			</if>
			<if test="p.from_addr != null">
				,FROM_ADDR					/*수신자 주소*/
			</if>
			<if test="p.snd_yn != null">
				,SND_YN						/*전송 여부*/
			</if>
			<if test="p.snd_dt != null">
				,SND_DT						/*전송 일시*/
			</if>
		</trim>
		<trim prefix="VALUES (" suffix=")" prefixOverrides=",">
			#{g.tenant}
			, #{g.username}
			, #{g.now}
			, #{p.mail_id}
			, #{p.mail_set_id}
			<if test="p.mail_tit != null">
				, #{p.mail_tit}
			</if>
			<if test="p.mail_cont != null">
				, #{p.mail_cont}
			</if>
			<if test="p.to_nm_list != null">
				,#{p.to_nm_list}						/*송신자 이름 목록*/
			</if>
			<if test="p.to_addr_list != null">
				,#{p.to_addr_list}					/*송신자 주소 목록*/
			</if>
			<if test="p.cc_nm_list != null">
				,#{p.cc_nm_list}						/*CC 송신자 이름 목록*/
			</if>
			<if test="p.cc_addr_list != null">
				,#{p.cc_addr_list}					/*CC 송신자 주소 목록*/
			</if>
			<if test="p.bcc_nm_list != null">
				,#{p.bcc_nm_list}						/* BCC 송신자 이름 목록*/
			</if>
			<if test="p.bcc_addr_list != null">
				,#{p.bcc_addr_list}					/* BCC 송신자 주소 목록*/
			</if>
			<if test="p.from_nm != null">
				, #{p.from_nm}
			</if>
			<if test="p.from_addr != null">
				, #{p.from_addr}
			</if>
			<if test="p.snd_yn != null">
				, #{p.snd_yn}
			</if>
			<if test="p.snd_dt != null">
				, #{p.snd_dt}
			</if>
		</trim>
	</insert>


	<select id="findListSendMultiMail" resultMap="resultMap-findESAMTMailById">
		/* commonCode.findListSendMultiMail */
	    SELECT MAIL_ID
		    , MAIL_SET_ID
		    , MAIL_TIT
		    , MAIL_CONT
		    , FROM_ADDR
		    , FROM_NM
		    , BCC_ADDR_LIST
			, BCC_NM_LIST
			, CC_ADDR_LIST
			, CC_NM_LIST
			, TO_ADDR_LIST
			, TO_NM_LIST
		    , SND_DT
		    , SND_YN
		    , REG_DT
		    , REG_ID
	     FROM ESAMTML
	    WHERE SYS_ID = #{g.tenant}
	      AND SND_YN = 'N'
	</select>


	<resultMap type="map" id="resultMap-findMultiMailSendHistory">
		<result property="bcc_addr_list" column="BCC_ADDR_LIST" jdbcType="CLOB" javaType="string" />
		<result property="bcc_nm_list" column="BCC_NM_LIST" jdbcType="CLOB" javaType="string" />
		<result property="cc_addr_list" column="CC_ADDR_LIST" jdbcType="CLOB" javaType="string" />
		<result property="cc_nm_list" column="CC_NM_LIST" jdbcType="CLOB" javaType="string" />
		<result property="to_addr_list" column="TO_ADDR_LIST" jdbcType="CLOB" javaType="string" />
		<result property="to_nm_list" column="TO_NM_LIST" jdbcType="CLOB" javaType="string" />
		<result property="fail_cont" column="FAIL_CONT" jdbcType="CLOB" javaType="string" />
	</resultMap>
	<select id="findMultiMailSendHistory" resultMap="resultMap-findMultiMailSendHistory">
		/* mail.findMultiMailSendHistory 메일전송이력 조회 */
		SELECT A.SYS_ID
		, A.MAIL_ID
		, A.MAIL_SET_ID
		, A.FROM_ADDR
		, A.FROM_NM
		, A.BCC_ADDR_LIST
		, A.BCC_NM_LIST
		, A.CC_ADDR_LIST
		, A.CC_NM_LIST
		, A.TO_ADDR_LIST
		, A.TO_NM_LIST
		, A.FROM_NM
		, A.SND_DT
		, A.MAIL_TIT
		, B.SND_CLS
		, A.SND_YN
		, A.REG_ID
		, A.REG_DT

		FROM ESAMTML A
		INNER JOIN ESACFML B
		ON A.MAIL_SET_ID = B.MAIL_SET_ID
		WHERE A.MAIL_SET_ID = #{p.mail_set_id}
		<if test="p.from_date != null">
			AND A.SND_DT <![CDATA[>=]]> #{p.from_date}
		</if>
		<if test="p.to_date != null">
			AND A.SND_DT <![CDATA[<]]> #{p.to_date}
		</if>
		AND B.STS != 'D'
		ORDER BY A.SND_DT DESC
	</select>

</mapper>