기본 콘텐츠로 건너뛰기

180928 SMTP 방식으로 메일 전송, 압축 모듈

SMTP 방식으로 메일 전송 + 압축 모듈




1. 메일 전송(SMTP 방식)
 - 컴퓨터로 이메일을 전송할 때, sendMail, qmail 등의 메일 서버 프로그램을 사용함
 - 메일 client와 미리 정해진 규칙들을 사용하여 메일을 발송
 - 정해진 규칙 = SMTP 프로토콜
 - 텔넷으로 메일서버에 연결하여 SMTP 프로토콜에 맞게 명령을 내리면 메일이 발송됨

 1) pom.xml에 메일발송에 필요한 라이브러리 추가
 2) Controller 소스 작성


예) Controller 예제1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/** 자바 메일 발송 
 * @throws MessagingException 
 * @throws AddressException **/
@RequestMapping(value = "/mailSender"
public void mailSender(HttpServletRequest request, ModelMap mo) throws AddressException, MessagingException { 
    // 네이버라면 smtp.naver.com 을 입력
    // Google이라면 smtp.gmail.com 을 입력 
    String host = "smtp.naver.com"
        
    final String username = "XXXXXXXX";         //네이버 아이디를 입력. @ 이후 주소는 입력X 
    final String password = "YYYYYYYY";            //네이버 이메일 비밀번호를 입력
    int port=465;                                 //포트번호 
    
    //메일 내용 
    String recipient = "WWWWWWW@gmail.com";                 //받는 사람의 메일주소
    String subject = "메일테스트";                             //메일 제목
    String body = username+"님으로 부터 메일을 받았습니다.";     //메일 내용
    Properties props = System.getProperties();                 // 정보를 담기 위한 객체 생성 
    
    // SMTP 서버 정보 설정 
    props.put("mail.smtp.host", host); 
    props.put("mail.smtp.port", port); 
    props.put("mail.smtp.auth""true"); 
    props.put("mail.smtp.ssl.enable""true"); 
    props.put("mail.smtp.ssl.trust", host); 
    //Session 생성 
    Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { 
        String un=username; 
        String pw=password; 
        
        protected javax.mail.PasswordAuthentication getPasswordAuthentication() { 
            return new javax.mail.PasswordAuthentication(un, pw); 
        } 
    }); 
    session.setDebug(true);                                             //for debug 
    
    Message mimeMessage = new MimeMessage(session);                     //MimeMessage 생성
    mimeMessage.setFrom(new InternetAddress("XXXXXXXX@naver.com"));     //발신자 세팅 , 보내는 사람의 이메일주소를 한번 더 입력, @이후 주소까지 입력
    mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recipient)); //수신자 세팅 //.TO 외에 .CC(참조) .BCC(숨은참조) 도 있음 
    
    mimeMessage.setSubject(subject); //제목 세팅
    mimeMessage.setText(body);          //내용 세팅
    Transport.send(mimeMessage);     //javax.mail.Transport.send() 이용 
    
}
cs


예) Controller 예제2 (1과 다른 방식)
 - but, 전체적인 방식 자체는 비슷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package Example;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
public class MailExam {
    public static void main(String[] args){
        try{
            new MailExam();
        }catch(Exception e){
            System.out.println("Error");
        }
    }
    public MailExam() throws Exception{
    
        Properties props = new Properties();                        //프로퍼티 객체 생성
        props.setProperty("mail.transport.protocol""smtp");        //smtp 방식임 선언
        props.setProperty("mail.host""smtp.gmail.com");            //메일 호스트 주소 선언(다른 메일 주소로 변경 가능)
        props.put("mail.smtp.auth""true");                        //smtp 권한 획득
        props.put("mail.smtp.port""465");                            //포트번호
        props.put("mail.smtp.socketFactory.port""465");
        props.put("mail.smtp.socketFactory.class""javax.net.ssl.SSLSocketFactory");        //소켓 사용
        props.put("mail.smtp.socketFactory.fallback""false");
        props.setProperty("mail.smtp.quitwait""false");
         
        //권한 획득 + 발송자 이메일 리턴
        Authenticator auth = new Authenticator(){
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("nowonbun@gmail.com""");
            }
        };
        //세션 설정
        Session session = Session.getDefaultInstance(props,auth);
         
        MimeMessage message = new MimeMessage(session);
        message.setSender(new InternetAddress("nowonbun@gmail.com"));        //발송자 메일 주소
        message.setSubject("test");                                            //발송 메일 제목
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("nowonbun@naver.com"));        //수신자 메일 주소
         
        Multipart mp = new MimeMultipart();
        MimeBodyPart mbp1 = new MimeBodyPart();
        mbp1.setText("Test Contents");                                        //메일 내용 담기
        mp.addBodyPart(mbp1);
        //첨부 파일
        String filename = "f:\\test.xls";
        if(filename != null){
            if(fileSizeCheck(filename)){
                MimeBodyPart mbp2 = new MimeBodyPart();
                FileDataSource fds = new FileDataSource(filename);
                mbp2.setDataHandler(new DataHandler(fds));
                mbp2.setFileName(MimeUtility.encodeText(fds.getName(), "UTF-8""B"));
             
                mp.addBodyPart(mbp2);
            }else{
                throw new Exception("file size overflow !");
            }
        }
        //MIME 타입 설정
        MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
        mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
        mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
        mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
        mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
        mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
        CommandMap.setDefaultCommandMap(mc);
         
        message.setContent(mp);
         
        Transport.send(message);                                            //메일 발송
    }
    
    //파일 사이즈 체크
    protected boolean fileSizeCheck(String filename) {
        if (new File(filename).length() > (1024 * 1024 * 2.5)) {
            return false;
        }
        return true;
    }
}
cs



2. 자바 zip 압축모듈
 - 자바 파일 전송은 Java.IO를 이용
 - InputStream, OutputStream 이용: 바이트 자원이 아닌 바이너리 자원의 입, 출력
 - ZipInpitStream, ZipOutputStream 이용: 압축 파일의 입, 출력


예) 예제 소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
public class Zip {
    /**
     * 압축 메서드
     * @param path 경로
     * @param outputFileName 출력파일명
     */
    public static void compress(String path,String outputFileName) throws Throwable{
        //파일 인스턴스 생성
        File file = new File(path);
        //lastIndexOf는 오른쪽부터 문자열을 셈 => 파일 확장자 찾기에 주로 사용
        int pos = outputFileName.lastIndexOf(".");
        if(!outputFileName.substring(pos).equalsIgnoreCase(".zip")){
            outputFileName += ".zip";
        }
        // 압축 경로 체크
        if(!file.exists()){
            throw new Exception("Not File!");
        }
        // 출력 스트림 초기화
        FileOutputStream fos = null;
        // 압축 스트림 초기화
        ZipOutputStream zos = null;
        //압축, 출력 스트림 예외 체크
        try{
            fos = new FileOutputStream(new File(outputFileName));
            zos = new ZipOutputStream(fos);
            // 디렉토리 검색
            searchDirectory(file,zos);         
        }catch(Throwable e){
            throw e;
        }finally{
            if(zos != null) zos.close();
            if(fos != null) fos.close();
        }
    }
    /**
     * 다형성
     */
    private static void searchDirectory(File file, ZipOutputStream zos) throws Throwable{
        searchDirectory(file,file.getPath(),zos);
    }
    /**
     * 디렉토리 탐색
     * @param file 현재 파일
     * @param root 루트 경로
     * @param zos 압축 스트림
     */
    private static void searchDirectory(File file,String root,ZipOutputStream zos) throws Exception{
        //지정된 파일이 디렉토리인지 파일인지 검색
        if(file.isDirectory()){
            //디렉토리일 경우 재탐색(재귀)
            File[] files = file.listFiles();
            for(File f : files){
                searchDirectory(f,root,zos);
            }
        }else{
            //파일일 경우 압축
            compressZip(file,root,zos);
        }
    }
    /**
     * 압축 메서드
     * @param file
     * @param root
     * @param zos
     * @throws Exception
     */
    private static void compressZip(File file, String root, ZipOutputStream zos) throws Exception{
        FileInputStream fis = null;
        try{
            String zipName = file.getPath().replace(root+"\\""");
            // 파일을 읽어들임
            fis = new FileInputStream(file);
            // Zip엔트리 생성(한글 깨짐 버그)
            ZipEntry zipentry = new ZipEntry(zipName);
            // 스트림에 밀어넣기(자동 오픈)
            zos.putNextEntry(zipentry);
            int length = (int)file.length();
            byte[] buffer = new byte[length];
            //스트림 읽어들이기
            fis.read(buffer, 0length);
            //스트림 작성
            zos.write(buffer, 0length);
            //스트림 닫기
            zos.closeEntry();
             
        }catch(Throwable e){
            throw e;
        }finally{
            if(fis != null) fis.close();
        }
    }
    public static void main(String[] args){
        try{
            Zip.compress("d:\\test""d:\\test.zip");
        }catch(Throwable e){
            e.printStackTrace();
        }
    }
}
cs