반응형
V. 메일 수신 예제
=================

 이 장에서는 JavaMail API를 이용한 메시지 수신 예제인 MailReciever.java에 대하여 다루겠다.
MailReciever는 간단하게 POP3를 이용하여 수신함에서 메일 메시지를 가져다가 local disk에
저장하는 프로그램이다.  전체 코드는 MailReciever.java 화일로 첨부해놓았으며, 여기서는
주로 전체적인 기능 및 부분 코드로 설명하겠다.

  MailReciever를 실행 시키려면 우선 다음과 같이 메일 호스트, 사용자 아이디, 암호 그리고
메일을 저장할 디렉토리이름을 main 메소드 에서 변경하여 바꾼 후에 컴파일 하여 실행 시키면 된다.

MailReciever reciever = new MailReciever();
reciever.setHost("www.xxxx.yyyy");
reciever.setUser("aaaa");
reciever.setPassword("bbbb");
reciever.setHomeDir("c:/mail");
        
reciever.recieve();


1. constructor
-----------------------------------------

  MailReciever의 Constructor에서는 우선 다음과 같이 메일 처리를 위한 Session 객체를 
생성하고 있다. Session 객체는 member variable인 session에 대입하여 놓는다.

Properties props = System.getProperties();
session = Session.getDefaultInstance(props, null);


2. recieve()
-----------------------------------------
  실제 메일을 수신하는 메소드는 recieve() 메소드 이다.  recieve() 메소드는 session으로 부터
pop3 Store 객체를 생하고 INBOX folder를 생성하여 message를 수신한다.

......

// Get folder
Folder folder = store.getFolder("INBOX");
    
// Open read-write
folder.open(Folder.READ_WRITE);
    
// Get message
Message message[] = folder.getMessages();
......

메일을 목록을 저장할 index화일과 메시지들을 저장할 디렉토리를 생성한 후에 
각각의 메시지들을 processMessage() 메소드를 호출하여 처리한다.

// index open
File indexFile = File.createTempFile("list", ".idx", new File(getHomeDir()));
FileOutputStream fout = new FileOutputStream(indexFile.getPath(), true);
indexWriter = new BufferedWriter(new OutputStreamWriter(fout));
        
// make folder
mailFolderName = getHomeDir() + "/" + indexFile.getName() + ".dir";
File mailFolder = new File(mailFolderName);
mailFolder.mkdir();
        
// process message
for(int i=0; i < message.length; i++) {
    processMessage(message[i]);
}

.......


3. processMessage()
---------------------------------------
  processMessage() 메소드는 각각의 메시지에 대한 발신자, 제목, 발신일, 저장할 폴더 등
목록에 해당하는 내용을 만든다.

.............

 // from
 sarr = message.getHeader("From");
 if(sarr == null || sarr.length == 0) {
   from = "";
 }
 else {
  from = decodeString(sarr[0]);
 }
            
 // subject
 sarr = message.getHeader("Subject");
 if(sarr == null || sarr.length == 0) {
   subject = "";
 }
 else {
   subject = decodeString(sarr[0]);
  }
            
// send date
sendDate = message.getSentDate();

.................


  메시지의 내용을 저장할 message+msgIndex 디렉토리를 만든다.  메시지의 내용과 
첨부 화일을 저장해야 함으로 내용을 저장할 $content.message 화일은 미리 open해 놓는다.
message는 여러부분의 Part로 구성될 수 있으므로 processPart 메소드를 호출하여 처리한다.
메시지를 처리한 후에 index 부분을 write한다.

        
// open content writer
FileOutputStream fout = new FileOutputStream(msgFolderName + "/" + "$content.message");
contentWriter = new BufferedWriter(new OutputStreamWriter(fout));
        
//process part
System.out.println(message.getSubject());
processPart(message);        
        
// header white
indexWriter.write(from + "\t");
indexWriter.write(subject + "\t");
indexWriter.write(sendDate +"\t");
indexWriter.write(msgFolderName + "\t");
indexWriter.write(appendCount + "\n");

// close content writer
contentWriter.close();


4. processPart()
--------------------------------------
  processPart()는 우선 Part의 내용을 화일로 저장할지 아니면 메시지 내용으로 write할 지를
결정한다.

String fileName = part.getFileName();
String disposition = part.getDisposition();
boolean isAttachement = false;
        
if (fileName != null || disposition != null) {
  isAttachement = true;
}

......

  mime type에 따라 Part의 내용을 처리하되 "text/*" 일 경우는 내용 저장, "multipart/*" 일 경우는
이를 다시 Part로 나누어 재귀적으로 processPart() 메소드를 호출, 그리고 "message/rfc822" 일 경우는
다시 processPart()를 다시 호출 한다.  나머지 경우는 내용을 저장한다.


if (part.isMimeType("text/*")) {
    
  if(isAttachement) {
    saveFile(fileName, part.getContent());
    appendCount++;
  }
  else {
    saveContent(part.getContent());
  }
                            
} else if (part.isMimeType("multipart/*")) {
            
  Multipart mp = (Multipart)part.getContent();        
  for (int i = 0; i < mp.getCount(); i++) {
    processPart(mp.getBodyPart(i));
  }
    
} else if (part.isMimeType("message/rfc822")) {
            
  processPart((Part)part.getContent());
            
} else {
            
  Object obj = part.getContent();
        
  if(isAttachement) {
    saveFile(fileName, obj);
    appendCount++;                
  }
  else {
    saveContent(obj);
  }

}


5. saveFile()
--------------------------------------
  화일이름과 내용을 담은 Object를 주면 중복되지않게 화일 이름에 일련번호를 붙여
내용을 저장한다.  내용 Object 가 InputStream일 경우는 stream을 읽어 내용을 저장하고
아닐 경우는 String으로 만들어 저장한다.


6. saveContent()
--------------------------------------
  내용을 담은 Object를 받아들여 이미 열려있는 contentWriter에 내용을 write한다.
내용 Object 가 InputStream일 경우는 stream을 읽어 내용을 저장하고
아닐 경우는 String으로 만들어 저장한다.


7. 기타 methods
--------------------------------------
  toHangle 메소드는 문자열을 한글체계로 바꾸는 메소드이고, decodeString은
메일 메시지의 헤데 문자열이 encoding되어 있을 때 MimeUtility를 이용하여
decode 하는 메소드이다.  searchPattern은 encoding되어 있는 문자열을 구분해내는
역할을 한다. 

+ Recent posts