Whiteship's Note


JavaMail - 첨부파일 읽기

모하니?/Coding : 2008.08.07 18:19


            ...
            if (message.isMimeType("multipart/*")) {
                Multipart context = (Multipart) content;
                int count = context.getCount();
                for (int i = 0; i < count; i++) {
                    // sub mailMessage mapping
                    Part part = ((Multipart) content).getBodyPart(i);
                    ...
                    readFile(submm, part);
                    mm.addMailmessage(submm);
                }
            }
            ...

    private void readFile(MailMessage submm, Part p) throws MessagingException, IOException {
        String filename = p.getFileName();
        File file = null;
        if (filename != null) {
            InputStream in = p.getInputStream();
          FileOutputStream fout = new FileOutputStream(new File(filename));
          int c = in.read();
          while (c != -1) {
              fout.write(c);
              c = in.read();
          }
          fout.close();
          in.close();
        }
        submm.setFilename(filename);
    }

파일럿 삼아서 대강 작성한 코드입니다. 저런 코드를 그대로 쓰시면 안되겠죠. 첨부파일을 inputStream으로 읽어서 특정 폴더로 다시 FileOutputStream으로 복사해주는 코드가 필요하네요.
top


JavaMail - 첨부 파일 보내기

모하니?/Coding : 2008.08.07 10:41


앞서 살펴본 HTML에 이미지 동봉하기와 비슷합니다.

            messageBodyPart = new MimeBodyPart();
            DataSource fds = new FileDataSource("C:\\images\\1.jpg");
            messageBodyPart.setDataHandler(new DataHandler(fds));
            messageBodyPart.setFileName("1.jpg");

            // add it
            multipart.addBodyPart(messageBodyPart);

이렇게만 하면 되죠. 아까와 차이는 헤더 설정은 하지 않고, 파일 이름 설정을 추가했습니다.

사용자 삽입 이미지

이제 메일 쓰기는 끝났으니... 간단한 텍스트 메일 읽기, HTML 메일 읽기, 첨부 파일 읽기.. ㄱㄱㅆ
top


JavaMail - HTML에 이미지도 같이 보내기

모하니?/Coding : 2008.08.07 10:00


HTML로 <img> 태그 써서 외부에 있는 이미 파일 링크거는거야.. 별거 아니고 그냥 html만 문자열로 잘 그리면 되는거죠. 그런데, 그런 절대경로로 이미지 참조하는거 말고, 이미지 파일을 동봉해서 상대경로로 참조하게 하는 방법입니다.

http://www.rgagnon.com/javadetails/java-0504.html

위에 잘 나와있습니다. 이번에도 전 메소드 하나만 샥~ 바꾸면 끝..

    private MimeMessage getMimeMessage(Session session, String title,
            String contents, String to) {
        MimeMessage message = new MimeMessage(session);
        try {
            message.setSubject(title);
            message.setRecipient(RecipientType.TO, new InternetAddress(to));

            //
            // This HTML mail have to 2 part, the BODY and the embedded image
            //
            MimeMultipart multipart = new MimeMultipart("related");

            // first part  (the html)
            BodyPart messageBodyPart = new MimeBodyPart();
            String htmlText = "<H1>Hello</H1><img src=\"cid:image\">";
            messageBodyPart.setContent(htmlText, "text/html");

            // add it
            multipart.addBodyPart(messageBodyPart);
           
            // second part (the image)
            messageBodyPart = new MimeBodyPart();
            DataSource fds = new FileDataSource("C:\\images\\1.jpg");
            messageBodyPart.setDataHandler(new DataHandler(fds));
            messageBodyPart.setHeader("Content-ID","<image>");

            // add it
            multipart.addBodyPart(messageBodyPart);

            // put everything together
            message.setContent(multipart);
        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
        return message;
    }

message에는 Multipart를 붙이고 Multipart에는 여러 개의 BodyPart를 붙였네요. 흠.. 한 바디에는 HTML을 붙이고, 다른 한 바디에는 그 위에서 참조할 이미지를 붙였습니다. 저런식으로 보내는 거였군요. 이미지는 Content-ID로 참조를 했고, MimeBodyPart의 헤더에 Content-ID를 설정했군요..
top


JavaMail - pom.xml에 dependency 추가하기

모하니?/Coding : 2008.08.07 09:46


        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>

최신버전은 1.4.1 까지 release가 됐으나, maven repo에선 1.4까지만 받을 수 있었습니다. 로컬 리파 사용하시는 분들은 1.4.1을 아리훽터리나, 넥서스에 설치하신 담에 버전을 1.4.1로 바꿔주셔도 될듯.. 전 귀찮아서 구냥 1.4.

        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1</version>
        </dependency>

이건 뭔지 잘 모르겠는데, 메일에 첨부파일 붙일 때 사용하는 DataSource, FileDataSource, DataHandler 이녀석들이 여기에 들어있습니다.

둘 다 독립적인 라이브러리라서 다른 라이브러리는 전혀 끌고 오지 않습니다. 깔끔합니다.
top


JavaMail - HTML 메일 보내기

모하니?/Coding : 2008.08.07 09:25


이전 코드에서 getMessage부분에서 한 줄만 바꾸면 됨.

message.setText()로 보냈었는데, 이번에는 setContent("내용", "메일타입"); 형태로 보냄.
    private MimeMessage getMimeMessage(Session session, String title,
            String contents, String to) {
        MimeMessage message = new MimeMessage(session);
        try {
            message.setSubject(title);
            message.setContent("<h1>Hello world</h1>", "text/html");
            message.setRecipient(RecipientType.TO, new InternetAddress(to));
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return message;
    }

아직도 수정하지 않고 있는 예외 잡아먹는 코드.. 저 한 줄 고치는게 왜이리 귀찮을까; 말나온김에 고치기..

사용자 삽입 이미지
끝.


다음은 HTML에 이미지 동봉하기..


top


JavaMail - 간단한 Text 메시지 보내기

모하니?/Coding : 2008.08.07 09:16


로컬에 설치한 SMTP로 보내려고 했더니, 외부로 나가질 않는데, 외부로 내보내는 설정을 못찾아서 그냥 Gmail SMTP 사용해서 보내봅니다.

    public void sendMail(String id, String passwd, String title, String contents, String to) {
        Properties props = makeSMTPProperties();
        Authenticator auth = getAutheticator(id, passwd);
        Session session = Session.getDefaultInstance(props, auth);
        URLName urln = new URLName("smtp", "smtp.gmail.com", 587, "", id, passwd);
        
        SMTPSSLTransport trans = new SMTPSSLTransport(session, urln);
        trans.setStartTLS(true);

        try {
            MimeMessage message = getMimeMessage(session, title, contents, to);
            trans.send(message);
        } catch (MessagingException e) {
            e.printStackTrace();
        } finally {
            try {
                trans.close();
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        }
    }

    private Properties makeSMTPProperties() {
        Properties props = new Properties();
        props.put("mail.transport.protocol", "smtp");
      props.put("mail.smtp.starttls.enable","true");
      props.put("mail.smtp.host", "smtp.gmail.com");
      props.put("mail.smtp.auth", "true");
        return props;
    }

    private Authenticator getAutheticator(String id, String passwd) {
        Authenticator auth = new SMTPAuthenticator(id, passwd);
        Security.addProvider(new Provider());
        return auth;
    }

    private class SMTPAuthenticator extends Authenticator {
        private String id;
        private String passwd;
        public SMTPAuthenticator(String id, String passwd) {
            this.id = id;
            this.passwd = passwd;
        }
        public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(id, passwd);
        }
    }

    private MimeMessage getMimeMessage(Session session, String title,
            String contents, String to) {
        MimeMessage message = new MimeMessage(session);
        try {
            message.setSubject(title);
            message.setText(contents);
            message.setRecipient(RecipientType.TO, new InternetAddress(to));
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return message;
    }

역시 대충 코딩한거라... 잡아먹는 예외처리 ㅠ.ㅠ 아무래도 이클립스 기본 템플릿 코드를 바꿔야 할듯.
throw new RuntimeException(e);
요렇게..

다음은 HTML 메시지 보내기
top


JavaMail - POP3로 메일 읽어오기

모하니?/Coding : 2008.08.06 21:03


    private void readEmailListByPop3(String id, String passwd) {
        Properties props = makePOP3Properties();
        Authenticator auth = getAutheticator(id, passwd);
        Session session = Session.getDefaultInstance(props, auth);

        Store store = null;
        Folder folder = null;
        try {
            store = session.getStore("pop3");
            store.connect();
            folder = store.getFolder("INBOX");
            folder.open(Folder.READ_ONLY);
            messages = Arrays.asList(folder.getMessages());
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (MessagingException e) {
            e.printStackTrace();
        } finally {
            try {
                folder.close(false);
                store.close();
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        }
    }

대강 짠 코드라 손볼 곳이 많습니다.

1. Message 대신에 별도의 메시지 도메인 클래스를 만드는게 좋을 듯 하고,
2. 예외 처리도 제대로 해야겠죠.
3. 메일을 읽어올 곳이 INBOX가 휴지통이라면?
4. 메시지들을 저 클래스가 컬렉션으로 들고 있게 할 것인가..(지금은 자기가 들고 있음) 말 것인가..(호출한 쪽에서 들고 있게)
5. 메시지들을 전부 읽어오지 말고, 페이징 처리 비슷하게 할듯.
6. imap을 쓰는게 좋을까 pop3를 쓰는게 좋을까? 아니면 둘 다 써야 하는 이유가 있는걸까? 그럴 경우 대부분의 코드가 비슷하고 프로퍼티 설정이나, Store 생성자 인자만 바뀔뿐이니.. 코드를 잘 분리해야함.
7. 읽지 않은 새로운 메일만 읽어올 거라면?

흠.. 대강 이정도 생각나는데 다른 건 또 뭐가 있을까요?

top

TAG javamail, POP3

JavaMail 에러 잡기 - javax.mail.MessagingException: [EOF]

모하니?/Coding : 2008.08.06 20:01


javax.mail.MessagingException: [EOF]

이 에러는 윈도우에서 자동으로 시작한 SMTP 서비스를 끄고, 별도로 설치한 메일 서버(저는 Mailtraq)에서 SMTP 서비스를 켜주면 해결 됨. 포트를 제외한 모든 커넥션 설정이 Mailtraq에 돌아갈 SMTP 서비스로 되어 있는데 정작 SMTP 서비스는 Mailtraq에서 돌지 않고 윈도 서비스로 돌고 있었습니다. 포트가 같으니까 못 돌린거죠.

일단 SMTP로 메일 보내기까진 완성. 이제 IMap이랑 POP3로 메일함을 읽오보실까나.

top

TAG javamail