Dev/JSP & Servlet

메일서버 설치, 메일 전송 페이지 만들기

창문닦이 2019. 3. 6. 16:03

메일 서버 원리

  • 대부분 회사마다 메일서버는 별도로 존재한다. ex) mail.naver.com

  • 임직원의 수가 많아지면 서버 부하를 분산시키기 위해서, 메일 송수신에 따라 서버를 두개를 나눈다. ex) pop.naver.com,smtp.naver.com

  • SMTP (Simple Mail Transfer Protocol) : 메일을 보낼때 사용하는 프로토콜이다. 상업용으로 돈을 주고 사야한다.
  • POP (Post Office Protocol) : 메일을 받을때 사용
  • IMAP(Internet Mail Access Protocol) : POP3와 동일
    • POP3는 move 개념, IMAP은 copy 개념
  • 자주 사용하는 네이버 메일의 환경설정 조회를 통해 POP3/IMAP 설정을 확인해보자.

메일 송수신 서버 (pop, smtp )명을 설정 하여 다른 메일 클라이언트에서도 네이버 메일 수신이 가능하다.


메일 서버 설치

  1. 아파치에서 제공하는 메일 서버 james 다운로드한다. https://james.apache.org/download.cgi
  2. javamail api 다운로드한다. https://www.oracle.com/technetwork/java/index-138643.html
    mail.jar : 톰캣에서는 서블릿 컨테이너를 사용하는 환경에서는 JavaMail API를 다운로드 해야한다. (imap, pop, smtp와 같은 프로토콜을 제공하여 전자메일을 주고받을 수 있게 하는 자바 API. 
  3. Javabean Activation Framework 다운로드한다. https://www.oracle.com/technetwork/java/javase/downloads/index-135046.html
    activation.jar
    activation.jar : Javabeans Activation Framework 를 이용하면 간단한 텍스트 데이터에서부터 이미지, 비디오 등의 매우 복잡한 멀티미디어 데이터로 구성된 문서까지 다양한 데이터를 전송할 수 있다. 이를 담은 라이브러리.
  4. lib 폴더에 추가한다.

메일 서버(james) 가동여부 확인하기

다운로드 받은 james 하위의 bin 폴더에 존재하는 run.bat 파일을 실행한다. 
배치파일을 실행해서 위와 같이 cmd창에 메세지가 보인다면 정상적으로 메일서버가 가동된 것.

CMD에 telnet 명령어 처리가 안되는 경우

telnet은 윈도우즈 기능에 해당한다. 이럴 경우 제어판에서 텔넷 클라이언트 기능을 사용하도록 변경해주면 된다.

경로 : 제어판 - 프로그램 제거 또는 변경 - Windows 기능 사용/사용 안함

 

갑자기 telnet을 확인하려는 것은 서버가 정상적으로 가동되는 지 확인하기 위해서다.

cmd를 통하여 telnet localhost 4555 로 메일 서버에 접속하면 cmd 창이 위와 같이 바뀐다. 텔넷으로 서버에 접속한 것인데 기본 계정 아이디와 비밀번호는 root/root이다.
텔넷 명령어 listusers로 생성된 계정을 확인할 수 있다. 오타가 좀 났다..

 

 


메일 작성 페이지 

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>메일보내기</title>
</head>
<body>

<form action="sendMail_ok.jsp" method="post">

<table border="1" align="center" style="font-size: 10pt;" cellpadding="0" cellspacing="0">
<tr>
	<td>보내는사람 이름</td>
	<td><input type="text" name="senderName" size="50"/></td>
</tr>
<tr>
	<td>보내는사람 E-Mail</td>
	<td><input type="text" name="senderEmail" size="50"/></td>
</tr>
<tr>
	<td>받는사람 E-Mail</td>
	<td><input type="text" name="receiverEmail" size="50"/></td>
</tr>
<tr>
	<td>제목</td>
	<td><input type="text" name="subject" size="50"/></td>
</tr>
<tr>
	<td>내용</td>
	<td><textarea rows="8" cols="50" name="content"></textarea></td>
</tr>
<tr>
	<td colspan="2" align="center">
	<input type="submit" value="메일 보내기">
	</td>
</tr>
</table>
</form>

</body>
</html>
 

실행 페이지

메일 작성 페이지 

  • javax.mail.Session : Java Mail API를 사용하는 출발점이 되는 클래스.
  • javax.mail.Message : Message 클래스는 메일을 표현하기 위해 사용되는 추상 클래스로 주제, 수신자의 이메일주소, 발송자의 이메일 주소, 보낸 날짜와 같은 실제 이메일 메시지의 세부 사항을 나타낸다.
  • MimeMessage 클래스는 Message 추상 클래스로부터 상속받은 인터넷 메일 클래스로 메일에 여러 개의 파일을 첨부시켜서 사용
  • java.util.Properties는 getProperties()메소드를 사용하여 시스템의 환경변수 값을 얻어올 수 있다. 환경변수의 설정은 Key와 Value 쌍으로 저장(자료형 Map)되어 있다.

JavaMail API를 이용하여 메일을 전송하는 과정

  1. javax.mail.Session 클래스의 인스턴스를 구한다.
  2. javax.mail.Message 클래스를 사용하여 전송하고자 하는 메일 메시지를 작성한다. (여기서의 메세지는 text, html,file 등이 올 수 있다.)
  3. javax.mail.Transport 클래스를 사용하여 작성한 메일을 전송한다.
<%@page import="javax.mail.Transport"%>
<%@page import="javax.mail.internet.InternetAddress"%>
<%@page import="javax.mail.Message"%>
<%@page import="javax.mail.internet.MimeMessage"%>
<%@page import="javax.mail.Session"%>
<%@page import="java.util.Properties"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
	
	//sendMail페이지에서 보낸 5개의 데이터 받아야 함
	String senderName = request.getParameter("senderName");
	String senderEmail = request.getParameter("senderEmail");
	String receiverEmail = request.getParameter("receiverEmail");
	String subject = request.getParameter("subject");
	String content = request.getParameter("content");
	
	String host = "localhost"; //192.168.16.16 
	
	//1.javax.mail.Session 클래스의 인스턴스를 구한다.
	Properties prop = System.getProperties(); //시스템의 환경설정
	Session ssn = Session.getInstance(prop,null);//환경설정 세션 생성 (시스템의 정보를 읽어와서 세션을 생성)
	
	try{
		//2.javax.mail.Message 클래스를 사용하여 전송하고자 하는 메일 메시지를 작성
		MimeMessage message = new MimeMessage(ssn);//MimeMessage는 실제 메일내용을 담음
		
		//message객체에 메일속성 설정
		message.addRecipient(Message.RecipientType.TO, new InternetAddress(receiverEmail)); //수신인 설정
		message.setFrom(new InternetAddress(senderEmail,senderName,"UTF-8"));//발신인 설정
		message.setSubject(subject, "UTF-8");//제목 설정
		message.setContent(content,"text/plain;charset=UTF-8");//내용 설정
		
		//메일 전송
		//3.javax.mail.Transport 클래스를 사용하여 작성한 메일을 전송
		Transport tp = ssn.getTransport("smtp");//보낼때 사용하는 프로토콜
		tp.connect(host, "", "");//ip, id, pw 가상으로 진행하므로 id, pw 생략
		tp.sendMessage(message, message.getAllRecipients());
		tp.close();
		
		out.print("메일 전송 완료!!");
	}catch(Exception e){
		
	}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>확인페이지</title>
</head>
<body>

</body>
</html>

성공적으로 전송되고 해당 메세지가 조회된다.
시간이 지난 후에 수신된 메일을 확인할 수 있다.


첨부파일과 함께 메일 작성하기

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="<%=cp%>/mail/data/style.css" type="text/css"/>
<script type="text/javascript" src="<%=cp%>/mail/data/mail.js"></script>

</head>
<body onload="document.myForm.sendName.focus();">
<br/><br/>
<table width="600" border="2" cellpadding="0" cellspacing="0" bordercolor="#d6d4a6" align="center">

<tr height="40">
	<td style="padding-left: 20px;">
	<b>E_mail전송</b>
	</td>
</tr>
</table>

<br/><br/>
<form action="mailSend_ok.jsp" name="myForm" method="post" enctype="multipart/form-data">
<table width="600" border="0" cellpadding="3" cellspacing="0" align="center">

<tr>
	<td colspan="2" height="3" bgcolor="#dbdbdb" align="center"></td>
</tr>
<tr>
	<td width="140" height="30" bgcolor="#eeeeee" style="padding-left: 20px;">
	보내는 사람 이름
	</td>
	<td width="460" style="padding-left: 10px;">
	<input type="text" name="senderName" size="35" maxlength="20" class="boxTF">
	</td>
</tr>
<tr>
	<td colspan="2" height="1" bgcolor="#dbdbdb" align="center"></td>
</tr>
<tr>
	<td width="140" height="30" bgcolor="#eeeeee" style="padding-left: 20px;">
	보내는 사람 E-Mail
	</td>
	<td width="460" style="padding-left: 10px;">
	<input type="text" name="senderEmail" size="35" maxlength="20" class="boxTF">
	</td>
</tr>
<tr>
	<td colspan="2" height="1" bgcolor="#dbdbdb" align="center"></td>
</tr>
<tr>
	<td width="140" height="30" bgcolor="#eeeeee" style="padding-left: 20px;">
	받는 사람 E-Mail
	</td>
	<td width="460" style="padding-left: 10px;">
	<input type="text" name="receiverEmail" size="35" maxlength="20" class="boxTF">
	</td>
</tr>
<tr>
	<td colspan="2" height="1" bgcolor="#dbdbdb" align="center"></td>
</tr>
<tr>
	<td width="140" height="30" bgcolor="#eeeeee" style="padding-left: 20px;">
	제&nbsp;&nbsp;&nbsp;&nbsp;목
	</td>
	<td width="460" style="padding-left: 10px;">
	<input type="text" name="subject" size="64" maxlength="100" class="boxTF">
	</td>
</tr>
<tr>
	<td colspan="2" height="1" bgcolor="#dbdbdb" align="center"></td>
</tr>
<tr>
	<td width="140" height="30" bgcolor="#eeeeee" style="padding-left: 20px;">
	내&nbsp;&nbsp;&nbsp;용
	</td>
	<td width="460" style="padding-left: 10px;">
	<textarea rows="12" cols="62" name="content" class="boxTA"></textarea>
	</td>
</tr>

<tr><td colspan="2" height="1" bgcolor="#dbdbdb" align="center"></td></tr>
<tr><td colspan="2" height="10" ></td></tr>
<tr><td colspan="2" height="1" bgcolor="#dbdbdb" align="center"></td></tr>

<tr>
	<td width="140" height="30" bgcolor="#eeeeee" style="padding-left: 20px;">
	첨부파일
	</td>
	<td width="460" style="padding-left: 10px;">
	<input type="file" name="fileName" maxlength="100" size="48" class="boxTF"/>
	</td>
</tr>
<tr><td colspan="2" height="3" bgcolor="#dbdbdb" align="center"></td></tr>
</table>

<table width="600" border="0" cellpadding="3" cellspacing="0" align="center">
<tr align="center">
	<td height="40">
	<input type="button" value="전송하기" class="btn2" onclick="mailSend();"/>
	<input type="reset" value="다시입력" class="btn2" onclick="document.myForm.senderName.focus();"/>
	</td>
</tr>
</table>

</form>
</body>
</html>

첨부파일을 함께 전송하는 페이지

 


첨부파일과 함께 메일 전송하기

<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@page import="com.mail.MailSend"%>
<%@page import="java.io.File"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
	
	String root = getServletContext().getRealPath("/");
	String path = root + File.separator + "pds" + File.separator + "mailFile";
	
	//파일 객체 생성
	File f = new File(path);
	if(!f.exists())
		f.mkdirs();//해당경로파일 없을경우 디렉토리 생성
	
	String encType = "UTF-8";
	int maxFileSize = 10*1024*1024;
	
	//메일전송 객체 생성
	MailSend mail = new MailSend();
	
	//파일업로드
	MultipartRequest mr = new MultipartRequest(request,path,maxFileSize,encType,new DefaultFileRenamePolicy());
	mail.setSenderName(mr.getParameter("senderName"));
	mail.setSenderEmail(mr.getParameter("senderEmail"));
	mail.setReceiverEmail(mr.getParameter("receiverEmail"));
	mail.setSubject(mr.getParameter("subject"));
	mail.setContent(mr.getParameter("content"));
	
	//첨부파일
	String fileName = mr.getFilesystemName("fileName"); //mailSend.jsp에서 첨부파일의 fileName
	if(fileName!=null&&!fileName.equals("")){
		String fileFullPath = path + File.separator + fileName;
		mail.setFileFullPath(fileFullPath);
		mail.setOriginalFileName(mr.getOriginalFileName("fileName"));
	}
	
	mail.sendMail();
	out.print("메일 전송 완료!!");	

%>

송신 결과
수신한 메일함

public class MailSend {
	
	private String receiverEmail;
	private String senderName;
	private String senderEmail;
	private String subject;
	private String content;
	private String fileFullPath;//서버에 메일파일을 업로드한 뒤 첨부하여 전송하는 것으로 파일경로가 필요하다
	private String originalFileName;
	
	private String mailHost;//메일서버
	private String mailType;//메일타입
	
	//생성자(메일 호스트 지정 없을 경우 localhost)
	public MailSend(){
		this.mailHost = "localhost";
		this.mailType = "text/html;charset=UTF-8";
	}
	//오버라이드된 생성자(사용자가 메일호스트를 지정할 경우 반영)
	public MailSend(String mailHost){
		this.mailHost = mailHost;
		this.mailType = "text/html;charset=UTF-8";
	}
	
	public String getReceiverEmail() {
		return receiverEmail;
	}
	public void setReceiverEmail(String receiverEmail) {
		this.receiverEmail = receiverEmail;
	}
	public String getSenderName() {
		return senderName;
	}
	public void setSenderName(String senderName) {
		this.senderName = senderName;
	}
	public String getSenderEmail() {
		return senderEmail;
	}
	public void setSenderEmail(String senderEmail) {
		this.senderEmail = senderEmail;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getFileFullPath() {
		return fileFullPath;
	}
	public void setFileFullPath(String fileFullPath) {
		this.fileFullPath = fileFullPath;
	}
	public String getOriginalFileName() {
		return originalFileName;
	}
	public void setOriginalFileName(String originalFileName) {
		this.originalFileName = originalFileName;
	}
	public String getMailHost() {
		return mailHost;
	}
	public void setMailHost(String mailHost) {
		this.mailHost = mailHost;
	}
	public String getMailType() {
		return mailType;
	}
	public void setMailType(String mailType) {
		if(mailType.equalsIgnoreCase("TEXT")){
			this.mailType = "text/plain;charset=UTF-8";
		}else{
			this.mailType = "text/html;charset=UTF-8";
		}
	}
	
	
	public boolean sendMail(){
		
		try {
			//1.세션 생성
			Properties props = System.getProperties();
			props.put("main.smtp.host", mailHost);
			Session session = Session.getDefaultInstance(props,null);
			
			//2. 메일을 보낼 메세지 클래스 생성
			Message msg = new MimeMessage(session);
			//2-1. 보내는사람
			if(senderName==null||senderName.equals("")){
				msg.setFrom(new InternetAddress(senderEmail));//이름이 없을 경우 이메일주소만 전송
			}else{
				msg.setFrom(new InternetAddress(senderEmail,senderName,"UTF-8"));//이름이 있을 경우 함께 전송
			}
			//2-2. 받는사람
			msg.setRecipient(Message.RecipientType.TO, new InternetAddress(receiverEmail));
			//2-3. 제목
			msg.setSubject(subject);
			//2-4. HTML형식인 경우 엔터를 <br/>로 변환
			if(mailType.indexOf("text/html")!=-1){
				content = content.replaceAll("\n", "<br/>");
			}
			//2-5. 메일 내용과 파일을 MimeBodyPart로 나누어 담음
			makeMessage(msg);
			
			msg.setHeader("X-Mailer", senderName);
			
			//2-6. 메일보낸날짜
			msg.setSentDate(new Date());
			
			//3. 메일전송
			Transport.send(msg);
		
			//4. 메일 전송 후 파일 삭제(이게 없으면, 파일 보낸 후 계속 서버에 파일 존재)
			if(fileFullPath!=null){
				File f = new File(fileFullPath);
				if(f.exists())
					f.delete();
			}	
			
		} catch (MessagingException e) {
			System.out.println(e.toString());
			return false;
			
		} catch (Exception e) {
			System.out.println(e.toString());
			return false;
		}
		return true;
	}
	
	private void makeMessage(Message msg) throws MessagingException{
		
		if(fileFullPath==null||fileFullPath.equals("")){
			//파일을 첨부하지 않았을경우
			msg.setText(content);
			msg.setHeader("Content-Type", mailType);
		}else{
			//파일을 첨부한 경우
			//1. 메일내용
			MimeBodyPart mbp1 = new MimeBodyPart();
			mbp1.setText(content);
			mbp1.setHeader("Content-Type", mailType);
			
			//2. 첨부파일
			MimeBodyPart mbp2 = new MimeBodyPart();
			FileDataSource fds = new FileDataSource(fileFullPath);//fileFullPath는 파일의 실제 물리적인 주소
			mbp2.setDataHandler(new DataHandler(fds));
			
			try {
				if(originalFileName==null||originalFileName.equals("")){
					mbp2.setFileName(MimeUtility.encodeWord(fds.getName()));
				}else{
					mbp2.setFileName(MimeUtility.encodeWord(originalFileName));
				}
			} catch (UnsupportedEncodingException e) {//try문에서 에러 발생시 UnsupportedEncodingException에서 예외처리됨
				System.out.println(e.toString());
			}
			
			//내용과 파일 합침
			Multipart mp = new MimeMultipart();
			mp.addBodyPart(mbp1);
			mp.addBodyPart(mbp2);
			
			//메세지 클래스에 content 입력
			msg.setContent(mp);
		}
		
	}

}
​

메일 송신 완료 후 서버상에 물리적 파일이 존재하지 않음을 볼 수 있다.

전송이 완료된 후에 별도로 파일을 관리하지 않을 것이다. 120~125 라인을 작성해서 첨부파일과 함께 메일 전송시, 파일 삭제가 진행된다.


메일서버 설치 및 운영

참조 :https://m.blog.naver.com/PostView.nhn?blogId=takakobj&logNo=110150902307&proxyReferer=https%3A%2F%2Fwww.google.com%2F