'javamail'에 해당되는 글 3건

  1. 2010.01.28 JavaMail 첨부파일 읽기
  2. 2010.01.27 JavaMail with IMAP
  3. 2010.01.15 JavaMail을 이용하며 메일전송
프로그래밍/JAVA2010.01.28 11:21
 과거 Arpanet 이메일의 표준(RFC 822)은 특별히 텍스트 메시지를 위해 디자인되었다. 당시에는 텍스트 이메일만이 사용가능한 타입이었기 때문이다. 하지만 1990년대 초반에 들어와서 기술적 수준이 발달함에 따라 RFC 822의 한계가 명백하게 드러나기 시작했다. 텍스트가 아닌, 다중 형식 이메일에 대한 지원의 필요성이 커지게 된 것이다.  여러 타입의 이메일을 지원하기 위해 인터넷 엔지니어들은 다중목적 인터넷 메일 확장 메커니즘(Multipurpose Internet Mail Extensions mechanism)인 MIME RFC 1341를 만들었다. 

MIME은 단일 메세지에 하나 이상의 아이템을 전달하기 위해 이메일 메세지 바디를 구성하는 방법을 정의한다.

1. 첨부파일 분리하기
하나의 메세지는 다수의 메세지 바디를(BodyPart)를 통해 구성되어 있다. 메세지에서 첨부파일을 찾아 분리해 내기 위해 메세지를 구성하는 바디를 재귀적으로 검사하면 된다.

다음은 첨부파일이 XML파일인 경우 로컬로 다운로드 하는 예제이다.
public static void saveAttachedFile(Part p) throws MessagingException, IOException {
		String fileName = p.getFileName();
		if( fileName != null ) {
			String type = p.getContentType();
			if( type.contains("text/xml") || type.contains("TEXT/XML") ) {
				File f = new File(fileName);
				((MimeBodyPart)p).saveFile(f);
			}
		}
		if( p.isMimeType("multipart/*") ) {
			Multipart mp = (Multipart)p.getContent();
			int count = mp.getCount();
			for(int i=0; i<count; i++)
				saveAttachedFile(mp.getBodyPart(i));
		}
	}

'프로그래밍 > JAVA' 카테고리의 다른 글

이클립스에서 JUnit 사용하기  (0) 2010.04.22
Java 어노테이션(Annotation)  (0) 2010.04.21
Java Decompiler jad  (2) 2010.03.17
Apache Xml Security을 이용한 XML 전자서명  (1) 2010.03.17
MSSQL with JDBC  (0) 2010.02.03
JavaMail 첨부파일 읽기  (0) 2010.01.28
JavaMail with IMAP  (0) 2010.01.27
JavaMail을 이용하며 메일전송  (0) 2010.01.15
RSA 암호화  (0) 2010.01.15
Java 쓰레드  (0) 2009.12.04
스트러츠 properties 한글 편집  (0) 2009.12.03
Posted by devop

댓글을 달아 주세요

프로그래밍/JAVA2010.01.27 11:03
JavaMail1.4.3은 IMAP4와 IMAP4rev1을 지원하며, IMAP의 주요 특성을 요약하면 다음과 같다.

  • 지속적으로 메세지 상태 플래그를 처리할 수 있다. 이러한 플래그에는 SEEN, DELETE, ANSWERED, RECENT 등이 있다.
  • 여러 편지함을 관리하고 접근할 수 있다. 받은 편지함과 다른 편지함에 접근하고 이름짓는 기능이 있기 때문에 가능하며 이들의 목록을 보고, 편지함을 생성, 삭제하고 이름을 바꾸는것도 가능하다.
  • 메일내용을 가져올 뿐만 아니라 저장할 수 있다. 사용자의 임의의 편지함으로부터 원하는 편지함으로 메일을 이동시킬 수 있다.
  • 메일 이외의 데이터도 접합하다. 이러한 기능은 서로 다른 정보를 동일한 방법으로 접근할 때 편리하다.
  • 온라인 성능을 최적화(특히 저속 링크일 경우)할 수 있다. 이것은 메세지 다운로드 없이 메세지 구조 가져오기 기능, 선택적으로 부분 메세지를 가져오는 기능, 클라이언트와 서버사이의 데이터 전송량을 줄이기 위해 서버를 검색하는 기능을 포함한다. 특히 작은 대역폭을 가지는 전송로를 통하여 메일 서버에 접속하고 있을 때 전송 메세지와 바로 필요하지 않는 메세지를 분리할 수 있다는 것은 아주 유용하다.

다음은 IMAP과 POP의 접근에 공통된 인터페이스를 제공하기 위한 선언이다.
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Store;

public interface MailProto {

	abstract public void open(String host, String id, String passwd) throws MessagingException;
	
	abstract public void close() throws MessagingException;
	
	abstract public Message getMessages(int msgNum) throws MessagingException;
	
	abstract public Message[] getMessages() throws MessagingException;
	
	abstract public Message[] getRecentMessages(int count) throws MessagingException;
	
	abstract public int getMessageCount() throws MessagingException;
	
	abstract public String getUID(Message msg) throws MessagingException;
	
	abstract public Folder getFolder() throws MessagingException;
	
	abstract public Store getStore() throws MessagingException;
}
다음은 MailProto 인터페이스를 사용한 IMAP 구현체이다.
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;

import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPStore;

public class IMAP implements MailProto {
	
	protected Session session;
	
	protected Store store;
	
	protected Folder folder;
	
	private static String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
	
	@Override
	public void open(String host, String id, String passwd) throws MessagingException {
		Properties props = new Properties();
		props.setProperty("mail.imap.socketFactory.class", SSL_FACTORY);
		props.setProperty("mail.imap.socketFactory.fallback", "false");
		props.setProperty("mail.imap.port", "993");
		props.setProperty("mail.imap.socketFactory.port", "993");
		session = Session.getInstance(props, null);
		URLName urlName = new URLName("imap", host, 993, "", id, passwd);
		store = new IMAPStore(session, urlName);
		store.connect();
		folder = store.getDefaultFolder().getFolder("INBOX");
		folder.open(Folder.READ_WRITE);
	}
	
	@Override
	public void close() throws MessagingException {
		if( folder != null && folder.isOpen() )
			folder.close(true);
		if( store != null && store.isConnected() )
			store.close();
	}
	
	@Override
	public Message getMessages(int msgNum) throws MessagingException {
		if( !folder.isOpen() )
			throw new MessagingException("Already closed folder");
		return folder.getMessage(msgNum);
	}
	
	@Override
	public Message[] getMessages() throws MessagingException {
		if( !folder.isOpen() )
			throw new MessagingException("Already closed folder");
		return folder.getMessages();
	}
	
	@Override
	public Message[] getRecentMessages(int count) throws MessagingException {
		if( !folder.isOpen() )
			throw new MessagingException("Already closed folder");
		int folderSize = folder.getMessageCount();
		return folder.getMessages(folderSize-count+1, folderSize);
	}
	
	@Override
	public int getMessageCount() throws MessagingException {
		if( !folder.isOpen() )
			throw new MessagingException("Already closed folder");
		return folder.getMessageCount();
	}
	
	@Override
	public String getUID(Message msg) throws MessagingException {
		if( folder instanceof IMAPFolder ) {
			return new Long(((IMAPFolder)folder).getUID(msg)).toString();
		}
		else {
			throw new MessagingException("Can not support");
		}
	}

	@Override
	public Folder getFolder() throws MessagingException {
		if( !folder.isOpen() )
			throw new MessagingException("Already closed folder");
		return folder;
	}

	@Override
	public Store getStore() throws MessagingException {
		if( !store.isConnected() )
			throw new MessagingException("Already closed store");
		return store;
	}
}
다음은 MailProto 구현체의 호스트 클래스로서 IMAP과 POP에 모두 공통적으로 이용할 수 있다.
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Store;

public class MailAgent {

	protected MailProto mailProto;
	
	protected String host;
	
	protected String id;
	
	protected String passwd;
	
	public MailAgent(MailProto mailProto, String host, String id, String passwd) {
		if( mailProto == null || host == null || id == null || passwd == null )
			throw new IllegalArgumentException();
		this.mailProto = mailProto;
		this.host = host;
		this.id = id;
		this.passwd = passwd;
	}
	
	public void open() throws MessagingException {
		mailProto.open(host, id, passwd);
	}
	
	public void close() throws MessagingException {
		mailProto.close();
	}
	
	public Message getMessage(int msgNum) throws MessagingException {
		return mailProto.getMessages(msgNum);
	}
	
	public Message[] getMessage() throws MessagingException {
		return mailProto.getMessages();
	}
	
	public Message[] getRecentMessages(int count) throws MessagingException {
		return mailProto.getRecentMessages(count);
	}
	
	public String getUID(Message msg) throws MessagingException {
		return mailProto.getUID(msg);
	}
	
	public int getMessageCount() throws MessagingException {
		return mailProto.getMessageCount();
	}
	
	public Folder getDefaultFolder() throws MessagingException {
		return mailProto.getFolder();
	}
	
	public Store getStore() throws MessagingException {
		return mailProto.getStore();
	}
	
	public MailProto getMailProto() {
		return mailProto;
	}
	
	public void setMailProto(MailProto mailProto) {
		this.mailProto = mailProto;
	}
}
다음은 MailAgent를 상속하여 POP과는 차별되는 IMAP의 고유 기능을 지원하기 위한 클래스이다.
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Flags.Flag;
import javax.mail.search.FlagTerm;

public class IMAPAgent extends MailAgent {
	
	public IMAPAgent(String host, String id, String passwd) {
		super(new IMAP(), host, id, passwd);
	}
	
	public Folder getFolder(String name) throws MessagingException {
		return getStore().getFolder(name);
	}
	
	public Message[] getUnReadMessages() throws MessagingException {
		return getDefaultFolder().search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
	}
	
	public void createFolder(String name) throws MessagingException {
		Folder folder = getStore().getFolder(name);
		if( !folder.exists() ) {
			folder.create(Folder.HOLDS_MESSAGES);
		}
	}
	
	public void moveMessage(Message[] message, Folder src, Folder dest) throws MessagingException {
		src.copyMessages(message, dest);
		src.setFlags(message, new Flags(Flags.Flag.DELETED), true);
	}
	
	public void setSeenFlag(Message message) throws MessagingException {
		setFlags(message, Flags.Flag.SEEN, true);
	}
	
	public void setUnSeenFlag(Message message) throws MessagingException {
		setFlags(message, Flags.Flag.SEEN, false);
	}
	
	public void setFlags(Message message, Flag flag, boolean set) throws MessagingException {
		message.setFlag(flag, set);
	}
	
	public boolean hasNewMessage(Folder folder) throws MessagingException {
		return folder.hasNewMessages();
	}	
}
다음은 IMAP 서버에 접속하여 읽지않은 메일을 읽음으로 표시하고 newFolder라는 곳으로 메일을 이동시키는 예제이다.
public static void readEmail() throws Exception {
		IMAPAgent mailagent = new IMAPAgent("pop.hanmail.net", "주소@hanmail.net", "비밀번호");
		mailagent.open();
		mailagent.createFolder("newFolder");
		Message[] msg = mailagent.getUnReadMessages();
		for(Message m : msg) {
			System.out.println("subject: "+m.getSubject());
			System.out.println("MsgNum: "+m.getMessageNumber());
			System.out.println("UID: "+mailagent.getUID(m));
			System.out.println("Sent Date: "+m.getSentDate());
			mailagent.setSeenFlag(m);
		}
		mailagent.moveMessage(msg, mailagent.getDefaultFolder(), mailagent.getFolder("newFolder"));
		mailagent.close();
	}
다음은 위 메세드를 실행하기전 메일함의 모습이다. 2개의 메일중 하나가 읽지 않음 상태에 있으며, newFolder는 존재하지 않는다.


메서드를 실행하면 메일함은 다음과 같이 변경된다. 읽지않음 메일은 읽음으로 상태 플래그가 변경되었으며, newFolder라는 새로운 폴더가 생성되었고 이 폴더로 메일이 이동되었다.


'프로그래밍 > JAVA' 카테고리의 다른 글

Java 어노테이션(Annotation)  (0) 2010.04.21
Java Decompiler jad  (2) 2010.03.17
Apache Xml Security을 이용한 XML 전자서명  (1) 2010.03.17
MSSQL with JDBC  (0) 2010.02.03
JavaMail 첨부파일 읽기  (0) 2010.01.28
JavaMail with IMAP  (0) 2010.01.27
JavaMail을 이용하며 메일전송  (0) 2010.01.15
RSA 암호화  (0) 2010.01.15
Java 쓰레드  (0) 2009.12.04
스트러츠 properties 한글 편집  (0) 2009.12.03
Java XML Parser JDOM  (2) 2009.09.03
Posted by devop
TAG imap, javamail

댓글을 달아 주세요

프로그래밍/JAVA2010.01.15 14:36
인터넷에서 메일을 주고받기 위한 프로토콜로 STMP, POP3, IMAP등이 존재한다.

  • SMTP: Simple Mail Transfer Protocol의 약자이며 영어 뜻 그대로 메일을 전송하기 위한 규약이다. 즉, SMTP 클라이언트와 SMTP 서버간에 정보를 주고 받기 위한 규약이다. SMTP는 실제로 파일이나 다양한 종류의 자료형식을 지원해 주기위하여 MIME이라는 형식을 이용한다.
  • IMAP: Internet Message Access Protocol의 약자이며 서버상에 저장되어 있는 메일을 원격상에서 접근하기 위한 통신규약이다.
  • POP3: Post Protocol version3의 약자이며 IMAP과 같이 서버상에 저장되어 있는 메일을 원격상에서 접근하기 위한 통신규약이다.

즉, 메일을 전송할 때는 SMTP를 이용하며, 메일을 읽어올 때에는 IMAP이나 POP3를 이용한다.

Socket을 이용하여 이들 프로토콜을 규현하면 인터넷에서 메일을 자유롭게 송수신할 수 있다. 그러나 Java에서는 이미 이들 프로토콜을 구현하여 쉽게 사용할수 있는 JavaMail이라는 패키지를 제공한다.



메일 전송 클래스의 코드는 다음과 같다.
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.MimeMessage;

import com.sds.etax.mail.MailUtils;

public class MailWriter {

	private String host;
	
	private String fromId;
	
	private String passwd;
	
	private Address[] to;
	
	private String title;
	
	private String message;
	
	private boolean tlsSockEnable;
	
	public MailWriter(String host, String fromId, String passwd, Address[] to, String title, String message) throws IllegalArgumentException {
		this(host, fromId, passwd, to, title, message, true);
	}
	
	public MailWriter(String host, String fromId, String passwd, Address[] to, String title, String message, boolean tlsSockEnable) throws IllegalArgumentException {
		if( host == null || fromId == null || passwd == null || to == null || title == null || message == null )
			throw new IllegalArgumentException();
		this.host = host;
		this.fromId = fromId;
		this.passwd = passwd;
		this.to = to;
		this.title = title;
		this.message = message;
		this.tlsSockEnable = tlsSockEnable;
	}
	
	public void write() throws MessagingException {
		Message msg = makeMessage();
		Transport.send(msg);
	}
	
	public void write(Multipart multipart) throws MessagingException {
		if( multipart == null )
			throw new IllegalArgumentException();
		Message msg = makeMessage();
		msg.setContent(multipart);
		Transport.send(msg);
	}
	
	public void tlsSockEnable(boolean tlsSockEnable) {
		this.tlsSockEnable = tlsSockEnable;
	}
	
	private Message makeMessage() throws MessagingException {
		Properties props = new Properties();
		props.put("mail.transport.protocol", "smtp");
		props.put("mail.smtp.host", host);
		props.put("mail.smtp.auth", "true");
		if( tlsSockEnable ) 
			props.put("mail.smtp.starttls.enable", "true");
		Session session = Session.getInstance(props, new Authenticator() {
			public PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(fromId, passwd);
			}
		});
		Message msg = new MimeMessage(session);
		msg.setFrom(MailUtils.stringToAddress(fromId));
		msg.setRecipients(Message.RecipientType.TO, to);
		msg.setSubject(title);
		msg.setText(message);
		return msg;
	}
}
일반 텍스트만을 포함하는 메일은 write() 메소드를 통해 전송할 수 있으며, 첨부파일이나 이미지등의 파일을 메일과 함께 전송하기위해 write(Multipart multipart) 메소드를 사용한다.
public static MimeBodyPart makeTextMimeBodyPart(String text) throws MessagingException {
		if( text == null )
			throw new IllegalArgumentException();
		MimeBodyPart part = new MimeBodyPart();
		part.setText(text);
		return part;
	}

public static MimeBodyPart makeAttachMimeBodyPart(String filePath, String fileName) throws MessagingException {
		MimeBodyPart part = new MimeBodyPart();
		part.setDataHandler(new DataHandler(new FileDataSource(filePath)));
		part.setFileName(fileName);
        part.setDisposition(Part.ATTACHMENT);
		return part;
	}
위 클래스와 메소드를 이용해 다음과 같이 첨부파일을 포함한 메일을 전송할 수 있다.
MailWriter mailWriter = new MailWriter(
				"gmail.pop", "계정@gmail.com", "비밀번호",
				MailUtils.stringsToAddressArray(new String[]{"받는사람@gmail.com"}), 
				"test1", "");
		Multipart multipart = new MimeMultipart();
		multipart.addBodyPart(makeTextMimeBodyPart("this is test mail message"));
		multipart.addBodyPart(makeAttachMimeBodyPart("test.txt", "첨부파일이름"));
		mailWriter.write(multipart);

'프로그래밍 > JAVA' 카테고리의 다른 글

Java Decompiler jad  (2) 2010.03.17
Apache Xml Security을 이용한 XML 전자서명  (1) 2010.03.17
MSSQL with JDBC  (0) 2010.02.03
JavaMail 첨부파일 읽기  (0) 2010.01.28
JavaMail with IMAP  (0) 2010.01.27
JavaMail을 이용하며 메일전송  (0) 2010.01.15
RSA 암호화  (0) 2010.01.15
Java 쓰레드  (0) 2009.12.04
스트러츠 properties 한글 편집  (0) 2009.12.03
Java XML Parser JDOM  (2) 2009.09.03
JRE Detection  (0) 2009.08.11
Posted by devop

댓글을 달아 주세요