메일 호스팅 업체를 통해 계약된 기관들에 패치내역을 보내주고 있다.
근데 오전부터 발신에 대해 모든 동작이 중지했다.
서버 엔지니어로 무엇을 봐야할까
메일이 관련된 프로토콜은 SMTP, POP3, IMAP등등이 있다.
SMTP : Simple Mail Transfer Protocol, 이메일 전송 때 사용하는 플로토콜.
POP3 : Post Office Protocol 3, 이메일 수신할때 사용하는 프로토콜.
IMAP: Internet Message Access Protocol, 이메일 수신할때 사용하는 프로토콜이다.
네이버, 다음 등 메일을 사용할 때 환경설정을 들어가보면
이렇게 POP3/SMTP 혹은 IMAP/SMTP 조합을 볼수 있다.
이를 보면 SSL이 필요하다고 써져있다. SSL는 다음번에.
SMTP는 465 포트
POP3 는 995 포트/ IMAP 은 993 포트를 사용하고 있으니 방화벽에서 차단되는 이력이 있는지 체크해보자.
하지만 차단이력이 없는데도 불구하고 메일이 보내지지 않는다.
그렇다면 서버나 웹 페이지의 소스코드의 문제로 생각할수 있다.
위에서 한번 언급했듯이, 이 메일 호스팅업체는 SSL을 사용하기 때문에
SSL/TLS 서버 테스트를 하기위해 openssl를 사용해서 테스트 해보자.
현재 발신이 안되는 상태이므로 SMTP, 465포트를 사용한다.
[test@mailserver ~]$ openssl s_client -connect smtp.mailhost.co.kr:465
CONNECTED(00000003)
depth=3 C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services
verify return:1
depth=2 C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
verify return:1
depth=1 C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
verify return:1
depth=0 CN = *.mailhost.co.kr
verify return:1
---
Certificate chain
0 s:/CN=*.mailhost.co.kr
i:/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Domain Validation Secure Server CA
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Domain Validation Secure Server CA
i:/C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
2 s:/C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
i:/C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services
3 s:/C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services
i:/C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services
---
Server certificate
-----BEGIN CERTIFICATE-----
7clOtTxZSRZ7H39hdjYnvNkL 생략 R52r2dTo++yyFqGwD50LaYDDHZzfuhvQzWBhKqL2
-----END CERTIFICATE-----
subject=/CN=*.mailhost.co.kr
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Domain Validation Secure Server CA
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: ECDH, P-384, 384 bits
---
SSL handshake has read 6360 bytes and written 447 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE ~~
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: FAF589A26EB429E 생략
Session-ID-ctx:
Master-Key: AAE5F6497D38C66 생략
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
0000 - e8 ee d4 41 ed 95 7d d5-cb 68 eb c5 d9 a5 fa 5c ...A..}..h.....\
0010 - 43 7c 33 b0 1c 1b 3d bf-08 10 5b 58 79 7f fc 0f C|3...=...[Xy...
0020 -
0030 -
0040 -
0050 -
0060 - 생략
0070 -
0080 -
0090 - 51 ec 6b 06 44 5d c5 d5-c3 39 56 b6 cf 7c 5e 02 Q.k.D]...9V..|^.
00a0 - b2 97 48 09 ca 3d f6 7a-18 b0 a1 40 46 e1 4d f2 ..H..=.z...@F.M.
Start Time: 1741338795
Timeout : 300 (sec)
Verify return code: 0 (ok)
메일서버와의 통신은 정상적으로 된것을 확인했다.
그럼 실제로 메일 송/수신 테스트를 해보자.
--- SMTP 서버 통신 테스트 과정 ---
220 mailpx12 ESMTP ready # 메일서버에 정상적으로 통신이 되었다.
HELO ourcompany.co.kr # [서버 엔지니어가 입력] 회사에 등록된 도메인을 입력한다.
250 mailpx12 # 서버가 HELO명령을 수락하였다
AUTH LOGIN # [서버 엔지니어가 입력] 로그인 인증을 시작하겠다.
334 VXNlcm5h~~~~~~~~~bWU6 # 서버가 ID를 요구함
YWxsc2 # [서버 엔지니어가 입력] 발신전용 메일의 ID를 입력(BASE64로 인코딩 필요)
334 UGFzc3dvcmQ6 # 서버가 PW를 요구함
Q0ZTY2xvdWQ~~~~~~~~j # [서버 엔지니어가 입력] 발신전용 메일의 PW를 입력(BASE64로 인코딩 필요)
235 2.0.0 OK # 인증이 성공적으로 완료됨
MAIL FROM: <onlymail@mail.co.kr> # [서버 엔지니어가 입력] 발신 전용 메일 주소 입력
250 ok # 서버가 발신자 설정을 수락함
RCPT TO: <serverengineer@mail.co.kr> # [서버 엔지니어가 입력] 수신 받을 메일주소 입력
250 ok # 서버가 수신자 설정을 수락함
DATA # [서버 엔지니어가 입력] 이메일 내용을 입력하겠다고 선언
354 go ahead # 서버가 이메일 내용 입력을 기다림
Subject: test # [서버 엔지니어가 입력] 이메일 제목을 입력함
# [서버 엔지니어가 입력] 헤더와 본문 사이에 빈 줄 필요(중요!)
test메일 내용입니다 # [서버 엔지니어가 입력] 이메일 본문 내용
. # [서버 엔지니어가 입력] 단일 점으로 이메일 내용 입력 종료
250 ok 1741339182 qp 944852 # 이메일이 성공적으로 전송 큐에 추가됨(메시지 ID와 함께)
QUIT # [서버 엔지니어가 입력] SMTP 세션 종료 요청
221 mailhost.co.kr # 서버가 연결 종료 확인
[test@mailserver ~]$ # 쉘 프롬프트로 돌아옴(세션 종료)
좀 더 사용하기 쉽게 sh로 구현하였다.
touch mailtest.sh
chmod +x mailtest.sh
#!/bin/bash
# 변수 설정
SMTP_SERVER="smtp.mailserver.co.kr"
SMTP_PORT="465"
FROM_EMAIL="onlymail@mail.co.kr"
TO_EMAIL="serverengineer@mail.co.kr"
USERNAME="메일계정"
PASSWORD="메일비밀번호"
SUBJECT="test"
BODY="test메일 내용입니다"
# Base64 인코딩
USERNAME_BASE64=$(echo -n "$USERNAME" | base64)
PASSWORD_BASE64=$(echo -n "$PASSWORD" | base64)
# OpenSSL로 SMTP 서버에 연결하여 명령 실행
(
sleep 2
echo "HELO ourcompany.co.kr"
sleep 1
echo "AUTH LOGIN"
sleep 1
echo "$USERNAME_BASE64"
sleep 1
echo "$PASSWORD_BASE64"
sleep 1
echo "MAIL FROM: <$FROM_EMAIL>"
sleep 1
echo "RCPT TO: <$TO_EMAIL>"
sleep 1
echo "DATA"
sleep 1
echo "Subject: $SUBJECT"
echo ""
echo "$BODY"
echo "."
sleep 1
echo "QUIT"
) | openssl s_client -connect $SMTP_SERVER:$SMTP_PORT -quiet
방화벽/서버의 문제는 아닌게 입증되었다.
이러면 끝
근데 궁금하니까 사내 개발소스를 뜯어보자.
ERROR ExceptionResolver /depNtc102/send/sendMail.do [ERROR] : java.lang.NullPointerException
at com.test.cmm.util.SystemDevCacheUtil.getEnv(SystemDevCacheUtil.java:81)
웹 요청이 /depNtc102/send/sendMail.do 로 들어와서
sendMail 메소드에서 getEnv() 의 Null인 객체를 참조하다 터진거 같다.
SVN따기 귀찮은데.. 그냥 여기까지만 봐줘도 되지만 개발소스를 뜯어보자
SystemDevCacheUtil.Java
public void setEnvList() throws Exception{
this.commonSysEnvList=commonService.selectSysEnvList();
}
~
~
~
public ComSysEnvVO getEnv(String dutDiv, String optnDiv) throws Exception{
ComSysEnvVO result = new ComSysEnvVO();
for (ComSysEnvVO data : commonSysEnvList){ // 여기서 NullPointerException 발생
if (data.getOptnDiv().equals(optnDiv) && data.getDutDiv().equals(dutDiv)){
result = data;
}
}
return result;
}
ComSysEnvVO result 부분에서 NullpointerException 부분을 처리하기 위해
public ComSysEnvVO getEnv(String dutDiv, String optnDiv) throws Exception {
if(commonSysEnvList == null) {
setEnvList();
}
ComSysEnvVO result = new ComSysEnvVO();
for (ComSysEnvVO data : commonSysEnvList) {
if (data.getOptnDiv().equals(optnDiv) && data.getDutDiv().equals(dutDiv)) {
result = data;
}
}
return result;
}
setEnvList()부분이 메서드 선언을 가져와서 Null 처리 해주면 될거같다.
'IT > Linux' 카테고리의 다른 글
Bastion 서버를 위한 기본적인 SSH키값을 보는법과 alias (0) | 2025.03.17 |
---|---|
폐쇄망과 구글 폰트에 대한 접속 불가 이슈 (1) | 2025.03.12 |
기본적인 Tomcat 서비스를 올리기 위한 환경 설정(WAS) (1) | 2025.03.07 |
Tomcat 웹 서버의 SSL 인증서 관리 (1) | 2025.03.06 |
Tomcat Log 수집 방법(JUL, Log4j)과 Level 설정 (1) | 2025.03.05 |