본문 바로가기
프로젝트/개인프로젝트

회원가입할때 이메일인증 구현하기(java, web)-자바로 이메일 보내기

by 으노으뇨 2022. 3. 6.
반응형
SMALL

회원가입할때나 다른 인증, 또는 홍보 등등 이메일을 자주 접합니다.

이때 우리도 우리 프로젝트나 사이트에서 회원가입을 할때 인증 번호를 이메일로 보내서 인증을 완료한뒤 가입시키는

과정을 구현해주면 좋겠습니다.

이메일을 전송하는 기능을 위해서 필요할 것은

  1. 네이버 또는 구글 아이디(저는 구글아이디로 하겠음)
  2. pom.xml 에 의존성 주입 (또는 그래들)
  3. 웹단에서 서버로, 그리고 서버에서 웹단으로 호출하는 로직

총 3가지가 필요하며 부수적인것은 추가로 설명드리겠습니다.


1. 의존성 주입

		<dependency>
			<groupId>com.sun.mail</groupId>
			<artifactId>javax.mail</artifactId>
			<version>1.6.1</version>
		</dependency>

		<dependency>
			<groupId>com.sun.mail</groupId>
			<artifactId>javax.mail</artifactId>
			<version>1.6.1</version>
		</dependency>

pom.xml에 해당 의존성을 주입합니다. 꼭 저걸로 하셔야합니다.

안그러면 오류가 생깁니다. 나중에 반드시

2022.01.24 - [자바]java.lang.ClassNotFoundException: com.sun.mail.util.MailLogger-자바메일보낼때 오류

 

[자바]java.lang.ClassNotFoundException: com.sun.mail.util.MailLogger-자바메일보낼때 오류

개인 프로젝트를 진행하는 도중에 아래와 같은 오류가 발생했습니다. 현재 메일을 보내는 기능을 구현하는 중이었습니다. 콘솔 오류를 보니 기능적이라던가 흔한 null 포인트, 권한, 또는 타입오

uno-kim.tistory.com

나중에 오류가 생긴다면 해당 글을 확인해주세요!!


2. 웹단에서 이메일 체크하는 화면 만들기

			<div class="input-group mb-3">
                            <input type="text" class="form-control" placeholder="이메일" aria-label="Username" id="signupModalInputtedUserEmail">
                            <span class="input-group-text">@</span>
                            <input type="text" class="form-control" placeholder="naver.com" id="showSelectedValue" value ="naver.com" aria-label="Username" disabled='true' />
               	            <select class="form-select" aria-label="Default select example" onchange="selectEmailChange(this)">
  						    	<option selected value ="naver">네이버</option>
  							    <option value="google">구글</option>
  							    <option value="daum">다음</option>
  							    <option value="user_email_input">직접입력</option>
							</select>
                        </div>
                        <div class="d-grid gap-2 col-6 mx-auto">
                            <button type="button" class="btn btn-primary" id="checkEmail" onclick="checkEmail()">이메일 인증</button>
                        </div>
                        <div id='checkEmailConfirm' ></div>

최초화면입니다.

누르면 바꿀수있습니다.

첫번째로 구글을 선택, 두번째로 다음, 세번째로 직접입력이다.

해당 선택에 따라 값을 변경 또는 직접입력로직은 추후 업데이트하도록 하겠습니다.


3. 실제로 존재하는 이메일을 입력하고 해당 이메일로 메일을 전송하는 로직

<button type="button" class="btn btn-primary" id="checkEmail" onclick="checkEmail()">이메일 인증</button>

제가 만든 버튼입니다. 해당 버튼을 누르면 checkEmail()이라는 함수를 호출하게됩니다.

function checkEmail(){
    let showSelectedValue = document.getElementById('showSelectedValue');
    let signupModalInputtedUserEmail = document.getElementById('signupModalInputtedUserEmail');
    let regExp = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])/;
    let sumeIvt =  document.getElementById('signUpModalEmailInputValidateTest').value;
    let sumeUvt =  document.getElementById('signUpModalEmailUrlValidateTest').value

    if(showSelectedValue.value==null||showSelectedValue.value.length==0){
        sumeIvt ='false';
        showSelectedValue.className='form-control is-invalid';
    }else showSelectedValue.className='form-control';
    if(signupModalInputtedUserEmail.value ==null||signupModalInputtedUserEmail.value.length==0){
        sumeUvt ='false';
        signupModalInputtedUserEmail.className = 'form-control is-invalid';
    }else{
        signupModalInputtedUserEmail.className='form-control';
        sumeUvt ='true';
    }
    if(!(signupModalInputtedUserEmail.value.match(regExp)!=null)) alert('올바른 이메일을 입력해주세요');
    else sumeIvt='true';
    if(sumeIvt=='true'&&sumeUvt=='true'){
        const user_email = signupModalInputtedUserEmail.value+"@"+showSelectedValue.value;
        sendEmailForCheckValidation(user_email);
        checkEmailForValidate();
        countDown3min();
    }
}

해당 함수는 유효성 검사하는 함수입니다. 

입력받은 이메일이 숫자 또는 영어로만 이루어져있는지 유효성검사흘합니다. 만약 기호가 들어가있다면 올바른 이메을 입력하라는 얼럿창이 뜹니다.

또는 입력을 안했거나, 직접입력하라나는데 직접입력을 안했을때 등등 모두 해당합니다.

이후 정상적인 이메일이라고 판단되어지면 

마지막 줄에서 3번째인

sendEmailForCheckValidation(user_email);

함수를 호출합니다. 해당함수에서 이제 이메일을 보내는 자바에 값을 넘기고 통신하는 과정을 하게됩니다.

function sendEmailForCheckValidation(user_email) {
    const sendingVO = {
        "mail_sbst" : "CHK"
    ,   "mail_send_time" : "signup"  
    ,   "user_email" : user_email 
    }
    $.ajax({
        type: 'GET',
        url: '/user/checkEmail',
        async: false,
        data : sendingVO,
        dataType: 'JSON', 
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            setRandom(data);
        },
        error: function () {
            alert('통신실패!!');
        }
    });
}

sendingVO ={} 로 map형식의 object를 셋팅하고 있습니다.

이는 이메일을 보내 종류와 타이밍과 보낼 유저이메일을 넣어주고있습니다.

저의 경우는 혼자서 프로젝트를 하고있지만 엔터프라이즈급으로 설계를 해서 이메일을 보낼때 해당 mail_sbst, mail_send_time 등을 통해

회원가입때 보낼 양식, 생일축하이메일 양식, 홍보성 이메일 양식 등등을 따로 DB에 저장하여 관리하려고 해당 값들이 필요합니다. 

여러분들은 이메일 주소만 있으면 될터이니 중요하지 않게 생각하시고 넘어가시면됩니다.


4. 본격적으로 java에서 이메일 보내는 단계

@Controller
@RequestMapping(value = "/user")
public class CheckEmailSO
{
	@Autowired
	OperMailBOC operMailBOC;
	@RequestMapping(method = RequestMethod.GET, value = "/checkEmail")
	public @ResponseBody String sendGmail(Model model,
			@RequestParam Map<String, Object> param)
	{
		return operMailBOC.sendMailSetting(param);
	};
}

해당 url과 매핑된 SO를 호출합니다. 아까 ajax로 보낸 값이 모두 param에 정상적으로 넘어왔는지 확인해주시면됩니다.

디버깅한 화면입니다. 값들이 정상적으로 넘어왔습니다.

@Service
public class OperMailBOC
{
	@Autowired
	CheckEmailBO checkEmailBO;
	public String sendMailSetting(Map<String, Object> param)
	{
		Map<String, String> inMap = new HashMap<String, String>();
		inMap.put("mail_sbst", (String) param.get("mail_sbst"));
		inMap.put("user_email", (String) param.get("user_email"));
		inMap.put("mail_send_time", (String) param.get("mail_send_time"));
		return checkEmailBO.gmailSend(inMap);
	}
}

직접적으로 데이터를 다루는  BO단에 넘기기 전에 BOC에서 미리  inner해줄 값들을 셋팅하고있습니다.

param과 크게 값이 다르진않지만 inMap을 실질적으로 만듦으로써  mapper로 값을 유효하게 넘길 수 있게되었다.

저의 경우 구글이메일로 사용했습니다.

package com.aPlatform.controller.user.BO;

import java.util.Map;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.aPlatform.mappers.OperEmailMapper;
@Service
public class CheckEmailBO
{
	@Autowired
	OperEmailMapper operEmailMapper;
	public String gmailSend(Map<String, String> inMap)
	{
		Map<String, String> resMap = operEmailMapper.getOperationMail(inMap);
		Properties prop = new Properties();
		prop.put("mail.smtp.host", "smtp.gmail.com");
		prop.put("mail.smtp.port", 465);
		prop.put("mail.smtp.auth", "true");
		prop.put("mail.smtp.ssl.enable", "true");
		prop.put("mail.smtp.ssl.trust", "smtp.gmail.com");
		int random = (int) (Math.random() * 89999999) + 10000000;
		Session session = Session.getDefaultInstance(prop, new javax.mail.Authenticator() {
			protected PasswordAuthentication getPasswordAuthentication()
			{
				return new PasswordAuthentication(resMap.get("OPER_MAIL"), resMap.get("OPER_PASSWORD"));
			}
		});
		try
		{
			MimeMessage message = new MimeMessage(session);
			message.setFrom(new InternetAddress(resMap.get("OPER_MAIL")));
			message.addRecipient(Message.RecipientType.TO, new InternetAddress(inMap.get("user_email")));
			message.setSubject(resMap.get("MAIL_TITLE")); // 메일 제목을 입력
			message.setText(resMap.get("MAIL_TXT") + " \n " + random); // 메일 내용을 입력
			Transport.send(message); //// 전송
			return Integer.toString(random);
		}
		catch (AddressException e)
		{
			e.printStackTrace();
			return "AE";
		}
		catch (MessagingException e)
		{
			e.printStackTrace();
			return "ME";
		}
	}
}

우선은 해당 이메일을 보내는 자바입니다.

저의 경우에는 다른 웹페이지에 있는 방식과 동일하지만 데이터는 조금 다르게 처리했습니다.

부분적으로 설명드리겠습니다.

저의 경우는 이메일의 보내질 타이밍이나 양식에 따라 다르게 값을 가져오도록 하는 로직을 이용합니다.

	<select resultType="map" parameterType="map" id="getOperationMail">
		SELECT
    		EMAIL 				AS OPER_MAIL
		    ,   MAIL_PASSWORD 	AS OPER_PASSWORD
		    ,   MAIL_TITLE
		    ,   MAIL_TXT
		FROM 
 		   OPE_MAIL_DTL
		WHERE
 		   MAIL_SBST			=	#{mail_sbst}
 		   AND   MAIL_SEND_TIME	=	#{mail_send_time}
 	</select>

이렇게 양식과 타이밍을 통해서 DB를 검색하면 그에 맞는 이메일ID, 비밀번호, 보내질 제목, 보내질 내용 등을 해당 테이블에서 가져옵니다.

만약 덩그러니 자바에 비밀번호와 아이디가 노출되는 것을 막기위함이고, 상황 마다 다른이메일을 같은 매퍼를 통해 값들을 가져오기위해서 DB에 저장하는 것입니다.

실제로 제가 사용하는 이메일과 비밀번호가 저장되어있습니다.

컬럼을 보시면 Mail_SBST가 있는데 

CHK하는 형태, signup할때 나타나는 타이밍 등을 통해 

MailTitle, Mail_TXT컬럼도 가져오게됩니다.

		Properties prop = new Properties();
		prop.put("mail.smtp.host", "smtp.gmail.com");
		prop.put("mail.smtp.port", 465);
		prop.put("mail.smtp.auth", "true");
		prop.put("mail.smtp.ssl.enable", "true");
		prop.put("mail.smtp.ssl.trust", "smtp.gmail.com");

 위의 prop변수는 Properties 클래스이며 이는 Hashtable<Object,Object> 를 상속받는 객체이다.

해당 값들을 put해준다,

그리고 난수값을 생성해서 이메일에 담아서 보내주어야한다.

난수값을 생성하는 방법은 랜덤매서드를 이용했다.

int random = (int) (Math.random() * 89999999) + 10000000;
		Session session = Session.getDefaultInstance(prop, new javax.mail.Authenticator() {
			protected PasswordAuthentication getPasswordAuthentication()
			{
				return new PasswordAuthentication(resMap.get("OPER_MAIL"), resMap.get("OPER_PASSWORD"));
			}
		});

이 부분은 내 구글계정에 접근 하는 매서드이다. 

내 db에서 가져온 값의 메일아이디와 메일 비밀번호를 통해 진행된다.

접근에 성공한다면

		try
		{
			MimeMessage message = new MimeMessage(session);
			message.setFrom(new InternetAddress(resMap.get("OPER_MAIL")));
			message.addRecipient(Message.RecipientType.TO, new InternetAddress(inMap.get("user_email")));
			message.setSubject(resMap.get("MAIL_TITLE")); // 메일 제목을 입력
			message.setText(resMap.get("MAIL_TXT") + " \n " + random); // 메일 내용을 입력
			Transport.send(message); //// 전송
			return Integer.toString(random);
		}

트라이문으로 가게된다.

message는 map<String, String> 형식이다.

첫번째로 보내는이를 설정한다. 나는 당당하게 내 메일을 보내는이로 설정하기로 했다.

두번째는 보낼사람이다. 입력받아온 이메일(인증하려는 이메일)로 설정하면된다.

세번째는 제목설정이다. 내 db에서 가져온 제목을 설정한다.

네번째는 내용설정이다. 내 텍스트를 가져오며, 

마지막 send매서드를 통해 해당  message가 보내진다.

그리고 다시 웹단으로 생성한 인증번호를 return  하여 웹단에서 인증번호 참거짓을 판단하게됩니다.


5. 메일확인

정말로 메일이 왔습니다.

제 메일이 정상적으로왔고 인증문자가 도착했습니다. 

인증문자를 입력해보겠습니다.

이메일 인증이 완료된 화면입니다. 

이렇게 자바단에서 이메일을 보내는 방법을 알아보았고 덤으로 웹에서 이메일인증하는 것을 구현해보았습니다.

갑자기 이메일인증을했더니 밑에 생성되는 것은 추후 포스팅을 하겠습니다. 지금은 자바에서 이메일을 보내는 것이

주제였으니..ㅠ

반응형
LIST

댓글