반응형
IV. 메일 메시지 수신
======================

  메일 메시지의 수신은 우선 POP3나 IMAP은 지원하는 메일 서버가 있다는 전제로
될 수 있다.  그리고 메일서버에 메일을 수신할 수 있는 계정이 만들어져있고
수신함 즉 "INBOX"가 존재하여 타인이 메일 서버로 메시지를 보낼 때 이 수신함에
그 메시지가 저장이 되어야 한다. 

  이러한 환경이 설정되어 있어야 JavaMail API를 이용하여 메일 서버의 수신함에
저장된 메시지를 가져올 수 있다.  메일 서버와 통신을 하여 수신함에서 수신된 
메시지를 꺼내올 수 있는 실제 클레스들은 기본적으로 com.sun.mail.imap 과 
com.sun.mail.pop3 패키지로 제공되는데 만일 다른 제공자의 클레스를 사용하고자 
한다면 Session의 프로퍼티를 설정해야 한다.

  다음은 POP3 프로토콜을 이용하여 수신함에서 메시지를 가져와 발신자와
제목을 화면에 보여주는 예제이다.


String server = "www.xxx.zzz";
String user   = "aaaa";
String pass   = "bbbb";

// 프로퍼티 
Properties props = new Properties();

// 세션 객체 생성 
Session session = Session.getDefaultInstance(props, null);

// POP3 Store 연결
Store store = session.getStore("pop3");
store.connect(server, user, pass);

// INBOX Folder 가져옮
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);

// 수신된 메시지들을 Folder에서 가져옮
Message message[] = folder.getMessages();

for (int i=0, n=message.length; i<n; i++) {
   System.out.println(i + ": " + message[i].getFrom()[0] 
     + "\t" + message[i].getSubject());
}

// 연결을 끊는다.
folder.close(false);
store.close();
  
  위의 예에서 보듯이 POP3를 지원하는 메일 서버 주소, 아이디, 패스워드만 있으면
Stroe 객체를 통하여 서버와 연결하여 Folder객에체서 Message 객체들을 얻어와 메일을 수신할 
수 있다.  Message 객체는 메일을 구성하는 수신자, 발신자, 제목, 내용등이 모두들어
있다.

  Message객체에서 getFrom 메소드를 호출하면 발신자 경로를 추적할 수 있는 Address
Array를 받을 수 있다.  최종 발신자는 0 번째에 있다.  메일 메시지의 제목을 얻으려면
Message의 getSubject 메소드를 호출하면 된다.  이러한 수신자, 발신자 또는 제목 등은
메일은 헤더에 해당하는데, 이는 getHeader 메소드를 통하면 원본 String을 얻을 수 있다.

  String from = message.getHeader("From");
  String subject = message.getHeader("Subject");

위의 예제에서 원본 String은 MIME 규칙에 의해 Encoding되어 있는 경우가 있는데 이럴때는
java.mail.internet.MimeUtility의 decodeWord 메소드를 이용하여 원본을 복구해내야 한다.

  메시지의 내용을 받는 방법은 기본적으로 Message 클레스의 getContent 메소드를 이용하도록
되어 있다.  getContent 메소드는 Part 인터페이드에 정의 되어 있다.  하지만 메시지의
내용이 어떤형태로 구성되어 있는냐를 고려해야 한다.  

  메시지 내용의 MIME type이 "text/plain" 또는 "text/html"일 경우는 비교적 간단하게
처리할 수 있다.  getContent로 얻은 객체를 toString 메소드를 이용하여 문자열로 받을 수도
있고 또다를 방법은 getText 메소드를 이용하여 내용을 문자열로 받을 수 있다.  
내용이 어떠한 MIME TYPE을 하고 있는지는 isMimeType 메소드로 비교할 수 있다. 다음은
text로 구성된 메시지의 내용을 받은 예제이다.

  Message[] message = folder.getMessages();

  for(int i=0; i < message.length; i++) {

    if(message[i].isMimetype("text/*")) {
      String content = message[i].getContent().toString();
      System.out.println(content);
    }
    else if(message[i].isMimeType("multipart/*)) {
      ...
    }
    else {
      ...
    }

  }

 메시지의 내용이 첨부화일을 갖는 경우는 보통 MIME type이 "multipart" 로 되어 있다.
이러한 경우는 Message 객체 의 content를  Multipart 객체로 casting해야 처리할 수 있다.
Multipart는 여러가지 Part가 모여있는 형태임으로 각각의 BodyPart를 추출하여 기본 내용 
텍스트로 쓸 것인지 첨부화일로 쓸 것인지를 판단한다.

Part의 내용을 처리하는 기준은 getDisposition 함수를 이용하여 얻을 수 있는데 비교할 수 있는
Constants는 Part에 있는 Part.ATTACHMENT 와 Part.INLINE이다.  Part.ATTACHMENT는 첨부
화일이라는 의미이고 Part.INLINE은 내용을 화면에 표시한다는 의미이다. 다음은 본문은
화면에 표시하고 첨부는 화일에 저장하는 예제이다.

// 메시지가 multipart인 경우
if(message.isMimeType("multipart/*")) {

  // 내용을 Multipart로 만듬
  Multipart mp = (Multipart)message.getContent();

  // 각각의 part를 순서데로 처리
  for (int i=0, n=multipart.getCount(); i<n; i++) {

    // 처리될 body part
    Part part = multipart.getBodyPart(i));

    // 처리 기준을 가져옴
    String disposition = part.getDisposition();
    String filename    = part.getFileName();
    
    // disposition이 Attachment이거나 file name이 있으면 저장
    if((disposition != null && disposition.equals(Part.ATTACHMENT)) ||
       (filename != null)) {
      saveFile(filename, part.getInputStream());
    }
    // 본문 처리
    else {
      .......
    }

  }
}

else {
  ....
}

위의 예제는 Message의 MIME type이 "multipart/*" 일 때 처리하는 로직이며
saveFile 메소드는 이미 있다고 가정한다.  그리고 본문처리 로직은
적절히 화면이 보여주거나 다른 곳이 저장한다고 가정한다.

POP3 프로토콜을 수신함에 있는 메시지를 삭제하는 기능도 정의하고 있다.
따라서 다음과 같이 수신함에 있는 메시지를 받아온 다음 수신함에서 해당 메시지를 
삭제할 수도 있다.

메시지 삭제는 다음과 같은 메시지 상태 flag를 바꾸어줌으로서 가능한데 각가의 flag는
Flags 클레스에 정의되어 있다.

- Flags.Flag.ANSWERED 
- Flags.Flag.DELETED 
- Flags.Flag.DRAFT 
- Flags.Flag.FLAGGED 
- Flags.Flag.RECENT 
- Flags.Flag.SEEN 
- Flags.Flag.USER 

위의 flag들은 모든 메일 서버가 지원하는 것은 아니다.  각각의 메일 서버마다 지원하는
flag가 있고 지원하지 않는 flag가 있다.  그리고 POP3 프로토콜에서는 DELETED flag만을
지원하도록 되어 있다. 어떠한 flag들이 지원되는지 알려면 Folder 객체의 getPermanentFlags()
메소드를 이용하면 된다.

메시지의 삭제 방법은 우선 Folder 객체를 READ/WRITE 형으로 연 다음  Message 객체의 flag을 
DELETED 상태로 바꾼다.

folder.open(Folder.READ_WRITE);
.......
message.setFlag(Flags.Flag.DELETED, true);

실제 메시지가 삭제되는 시점은 folder를 close하는 시점인데 다음과 같이 파라미터에 true를
준다.

folder.close(true);

메시지를 수신하는 전반적인 방법은 다음 장에 Reciever.java 예제로 다시한번 설명하겠다. 

+ Recent posts