본문 바로가기
자격증

[리눅스마스터 1급] 12. 메일 서비스 (sendmail)

by LimSeongHyeon 2025. 5. 3.

 

메일 서비스

현실에서의 우편 배달

약간 억지스러운 부분이 있지만 다음과 같은 가정을 해보자.
"나는 경비원을 통해서만 우편을 받을 수 있는 고급 아파트 1203호 주민이다."
  1. 발신자는 우선 우편을 들고 우체국에 전달한다.
  2. 우체국은 발신자 이외에도 많은 우편들을 처리하며 먼저 전달받은 우편 먼저 우체부에게 전달한다.
  3. 우체부는 수신자 동네의 우체국에 우편을 전달한다.
  4. 수신자 동네의 우체국에서 일하는 우체부가 해당 우편을 들고 고급 아파트 우편함에 넣어둔다.
case 1
5-1) 1203호 우편함에 우편이 온 것을 확인한다.
5-2) 우편을 확인한 경비원은 우편을 들고 1203호에 가서 수신자에게 전달해준다.
case 2
5-1) 수신자가 먼저 경비원에게 우편이 왔는지 물어본다.
5-2) 경비원은 우편함에 1203호 우편이 와있는지 확인한다.
5-3) 우편이 확인되면 해당 우편을 들고 온다.
5-4) 해당 우편을 수신자에게 전달해준다.

 

더보기
경비원이라는 약간의 억지가 추가되었지만, 보안이 중요한 아파트라고 생각한다면 수신자의 신원을 확인하고 우편에 경비원만 출입해서 가져오는 형태가 훨씬 유리할 것이다. 메일 서비스는 아무나 개인 우편함에 접근해선 안되고, 신원이 보장되어야 하기 때문에 적절하지 않나 싶다. 개발이나 시스템 구조에서는 현실 세계를 투영한 구조가 많다는것을 다시 한 번 느낀다.

 


메일 서비스 플로우

위 시나리오를 그대로 메일 서비스의 프로토콜과 프로그램으로 재구성 하였다.
  1. MUA는 SMTP 프로토콜을 이용하여 MTA에 전송할 메일을 전달한다.
  2. MTA는 먼저온 메일을 처리해야 하기 때문에 Mail-Queue를 가지고, 순서대로 MDA에 전달한다.
  3. MDA는 SMTP 프로토콜을 이용하여 수신자 측 MTA에게 메일을 전달한다.
  4. 수신자 측 MTA는 수신자 MDA에게 전달한다.
  5. MDA가 Mail Box에 해당 메일을 저장한다.
IMAP Case
6-1) Mail Box는 메일이 들어옴을 IMAP Server에 Push 한다.
6-2) IMAP Server는 Push된 메일을 알맞는 MUA에게 전달한다.
POP3 Case
6-1) MUA는 주기적으로 POP3 서버에 메일이 왔는지 확인한다. (polling)
6-2) POP3 서버는 Mail Box에 메일이 왔는지 확인한다.
6-3) Mail Box에 메일이 와있다면 메일을 가져온다.
6-4) POP3 서버가 Mail Box에서 가져온 메일을 MUA에게 전달한다.

sendmail 설치 및 실행

$ dnf install -y sendmail
$ systemctl start sendmail.service
$ systemctl enable sendmail.service

 


sendmail 설정 파일

파일 설명
/etc/mail/sendmail.cf sendmail의 메인 설정 파일이다. 직접 수정은 권장되지 않는다.
/etc/mail/sendmail.mc sendmail.cf를 생성하기 위한 매크로 파일이다. m4 매크로 프로세서를 사용해 사람이 이해하기 쉬운 형태로 설정한다. "m4 sendmail.mc > sendmail.cf"
/etc/aliases 메일 별칭 정의 파일이다. 수정 후 "newaliases" 명령어 실행이 필요하다.
/etc/mail/access 릴레이 허용(RELAY) 및 차단(REJECT)을 위한 호스트 정의 파일이다.
수정 후 "makemap hash access < access" 실행이 필요하다.
/etc/mail/virtusertable 가상 사용자를 실제 사용자로 매핑하는 파일이다.
수정 후 "makemap hash virtusertable < virtusertable" 실행이 필요하다.
/etc/mail/local-host-names 서버가 수신할 수 있는 로컬 도메인 목록이 작성된다. 포함되지 않은 도메인 메일은 거부된다.
~/.forward 개별 사용자 메일을 자동으로 전달할 이메일을 설정한다.

 


 

sendmail.cf
항목 의미 설명
Cw Class w
(w = who are we?)
로컬 호스트 이름 지정 서버가 수신할 도메인 이름
ex) Cwlocalhost mydomain.com
Fw File Class w 외부 파일에서 Class w 로딩
ex) Fw /etc/mail/local-host-names
O AliasFile Option AliasFile
(O = Option)
별칭 파일 경로 지정 (aliases 파일)
ex) O AliasFile=/etc/aliases
Kaccess Map access
(K = Key Map)
접근 제어 테이블 매핑 정의 (access.db)
ex) Kaccess hash -o /etc/mail/access
Kvirtuser Map virtuser
(K = Key Map)
가상 사용자 테이블 매핑 정의 (virtusertable.db)
ex) Kvirtuser hash -o /etc/mail/virtusertable
FR-o File Ruleset o
(o = rule set name)
파일 내용을 Ruleset o로 로드
ex) FR-o /etc/mail/relay-domains
Dj Define j
(j = hostname)
현재 호스트의 FQDN(SMTP 대화/메일 헤더 표시 이름) 지정
ex) Djmail.mydomain.com
Dn Define n
(n = official hostname)
MTA의 공식 호스트명 지정
ex) Dnmailhost
O DeliveryMode Option DeliveryMode
(O = Option)
메일 전송 방식 지정
[immediate,deferred,queueonly,background]
ex) O DeliveryMode=background
O QueueDirectory Option QueueDirectory
(O = Option)
메일 큐 디렉토리 경로 지정
ex) O QueueDirectory=/var/spool/mqueue
O Timeout.queuereturn Option Timeout.queuereturn
(O = Option)
큐에 머문 메일이 실패로 간주되기 전 대기 시간
ex) O Timeout.queuereturn=5d
O DaemonPortOptions Option DaemonPortOptions
(O = Option)
SMTP 데몬의 바인드 포트/인터페이스 지정
ex) O DaemonPortOptions=Port=25, Name=MTA
O MaxMessageSize Option MaxMessageSize
(O = Option)
허용 최대 메일 크기 (bytes)
ex) O MaxMessageSize=10485760 (10MB)
O ForwardPath Option ForwardPath
(O = Option)
사용자 홈 디렉토리의 .forward 파일 위치 지정
ex) O ForwardPath=$z/.forward
Ft Format to 헤더 포맷 지정
ex) FtTo:

 


 

aliases

기본적으로 들어오는 메일에 대해 매크로 스타일의 처리를 원할 때 사용된다. 주 사용 목적은 아래와 같다.
1) 시스템 계정에 메일을 전달할 관리자를 지정.
2) 여러 사용자에게 동시에 메일 전달.
3) 메일을 파일 혹은 프로그램에 전달.
4) 특정 계정에 전달하지 않고 삭제 처리

 

 

단일 사용자에게 전달

root: admin

 

 

여러 사용자에게 전달

staff: alice,bob,carol

 

 

파일에 명시된 사용자에게 전달

admin: :include:/etc/mail_admin

 

 

외부 이메일로 전달

tmpstaff: tmpstaff@example.com

 

 

파일로 저장

logmail: /var/log/mail.log

 

 

프로그램으로 전달

filtermail: "|/usr/bin/myfilter"

 

 

변경 적용

$ newaliases

 


 

access

sendmail의 접근 제어 설정 파일이다. IP, 도메인, 메일 주소, 네트워크 단위로 허용 / 차단 / 릴레이 / 거부가 가능하다.

 

 

Action

OK 요청 허용 (릴레이 X)
REJECT 요청 거부 → SMTP 550
RELAY 릴레이 허용 (내 서버 → 외부 서버로 메일 중계 허용)
DISCARD 메일 수신한 척하고 폐기 (수신자에게 메일 전달 안 함, bounce도 없음)

 

 

Prefix

접두어 설명 예시
Connect: SMTP 연결 시 검사 (발신 IP) Connect:spammer.com REJECT
From: MAIL FROM 명령의 발신자 검사 From:badguy@example.com REJECT
To: RCPT TO 명령의 수신자 검사 To:vip@example.com RELAY
Auth: 인증된 사용자 이름 검사 Auth:trusteduser OK
ClientCert: 클라이언트 인증서 검증 ClientCert:CN=mailclient.example.com RELAY
TLS_Srv: TLS 서버 인증서 검증 TLS_Srv:CN=mailserver.example.com OK
TLS_Clt: TLS 클라이언트 인증서 검증 TLS_Clt:CN=mailclient.example.com OK
Helo: SMTP HELO/EHLO 도메인 검사 Helo:bad-helo.example.com REJECT

 

 

적용

$ makemap hash /etc/mail/access < /etc/mail/access

 


virtusertable
virtusertable은 이름에서 알 수 있듯 가상의 메일 계정을 실제 계정에 매핑하는 파일이다. 한개의 가상 계정에 여러개의 실제 계정을 대응 시킬 순 없다. 그럼 언제 사용하는지 알아보자.

 

 

1) 같은 사용자 명이라도 도메인에 따라 다른 사용자로 매핑해야 하는 경우.

info@example.com      com-manager
info@example.net      net-manager
info@example.org      org-manager
실제로 이런 경우가 사용되는지 모르겠지만, 회사 규모가 정말 크다면 도메인에 따라 분배해주는 것도 하나의 방법일 수 있겠다.

 


2) 로컬 계정 없이 메일만 포워딩 하는 경우.

support@example.com   real-support@example.net
사실 이 경우가 가장 많이 사용될 것 같다. 가령 우리 회사 직원은 아니지만 외부 인력이 해당 회사 소속의 수신 이메일이 필요한 경우 이메일 하나 때문에 시스템 계정 발급 및 관리를 해주어야 하는 불편함이 생길 수 있다. 이때 가상 메일 계정을 생성해서 본래 외부 인력이 쓰던 이메일로 포워딩 해주는 방식으로 사용하면 매우 편리할 것이다.

 


3) 도메인으로 들어오는 모든 메일을 특정 계정으로 전달하는 경우 (Catch-All)

@example.com          catchalluser
스팸으로 부터 안전하지 않아서 잘 사용하는 방법은 아닌 듯 하다.

 


4) 가상 메일 주소에 프로그램을 연결하는 경우

incoming@example.com   "|/usr/local/bin/processmail"
asliases 설정 뿐 아니라 virtusertable에서도 가상 계정으로 들어오는 메일을 바로 프로그램에 전달할 수 있다.

 

 

적용

$ makemap hash /etc/mail/virtusertable < /etc/mail/virtusertable

 

local-host-names

localhost
example.com
mail.example.com
mydomain.org
local-host-names는 내 메일 서버 도메인이 무엇인지 명시하는 파일이다. 메일을 받았을 때 local-host-names에 등록되어 있는 도메인으로 왔다면 메일 서버 규칙에 의해 처리하고, 등록되어 있지 않은 도메인으로 온 경우 릴레이로 간주하고 릴레이 정책으로 처리한다.

 

 

적용

systemctl restart sendmail

 

.forward

각 유저 홈 디렉터리에 설정 되어있는 .forward 파일에 포워딩을 원하는 메일 주소를 한 줄 씩 개행하여 작성한다.

 


 

sendmail 관리

명령어 설명
sendmail -v recipient 메일 전송 시 상세 출력 (verbose)
sendmail -t 헤더의 수신자 정보를 이용해 메일 전송
sendmail -q 메일 큐에 쌓인 메일 즉시 전송 시도
sendmail -q -v 큐 전송 시도 + 상세 출력
sendmail -bp 큐에 있는 메일 목록 출력 (mailq와 동일)
sendmail -bi /etc/aliases 파일을 재컴파일 (newaliases와 동일)
sendmail -bs SMTP 모드 (RFC821 세션)으로 동작 → SMTP 테스트 용도
sendmail -Am 메일 송신에 MTA 모드 사용 (postfix 계열과 호환 시)
mailq 큐에 있는 메일 목록 출력 (sendmail -bp의 alias)
mailq -Ac 클라이언트 큐 (MSP 큐) 상태 출력
자세한 내용은 man과 help를 확인해서 해결하는 것이 좋을 것 같다.

 


메일 발송

# 일반적인 메일 전송
$ echo "메일 본문" | mail -s "제목" recipient@example.com

# telnet으로 디버깅을 위한 메일 전송
$ telnet localhost 25

문제

설정

 

sendmail의 구성 파일을 생성하는 파일 전체 경로를 입력하세요.

더보기

/etc/mail/sendmail.cf

 

example.com 도메인으로 메일을 받을 수 있도록 설정하는 내용을 입력하세요.

더보기

IN MX 10 example.com

 

www 도메인의 A 레코드를 192.168.12.5로 설정하는 내용을 입력하세요.

더보기

www IN A 192.168.12.5

 

www1 도메인을 www에 연결하는 내용을 입력하세요.

더보기

www1 IN CNAME www

 

발신 도메인을 무조건 example.com으로 설정하는 내용을 입력하세요.

더보기

Djexample.com

 

매크로 파일을 이용해 sendmail의 구성 파일을 복원(적용)하는 명령어를 입력하세요.

더보기

$ m4 sendmail.mc > sendmail.cf


 

별칭

 

별칭 설정 파일의 전체 경로를 입력하세요.

더보기

/etc/aliases

 

manager 계정으로 오는 메일을 reduser와 blueser에게 전달 하도록 설정하는 내용을 입력하세요.

더보기

manager: reduser, blueuser

 

admin 계정으로 오는 메일을 /etc/mail_admin에 정의된 사용자에게 전달 하도록 설정하는 내용을 입력하세요.

더보기

admin: :include:/etc/mail_admin

 

변경된 별칭 파일의 내용을 적용하는 명령어를 입력하세요.

더보기

newaliases 또는 sendmail -bi

 


 

액세스

 

특정 도메인을 허용 및 거부하기 위한 정책 설정을 하는 파일의 전체 경로를 입력하세요.

더보기

/etc/mail/access

 

spam.com 도메인으로 부터 들어오는 연결을 거부하는 설정 내용을 입력하세요.

더보기

Connect:spam.com REJECT

 

spam.com 도메인으로 부터 들어오는 메일을 거부하는 설정 내용을 입력하세요.

더보기

From:spam.com REJECT

 

spam.com 도메인으로 부터 들어오는 메일을 수신한척 폐기하는 설정 내용을 입력하세요.

더보기

From:spam.com DISCARD

 

badguy@example.com이 보낸 메일을 거부하는 설정 내용을 입력하세요.

더보기

From:badguy@example.com REJECT

 

해당 액세스 변경 사항을 적용하기 위한 명령어를 입력하세요.

더보기

$ makemap hash /etc/mail/access < /etc/mail/access


 

포워딩

 

포워딩을 설정하기 위한 파일의 위치를 설명하는 내용을 입력하세요.

더보기

각 사용자의 홈 디렉터리의 .forward로 존재

 

포워딩 설정 내용을 어떻게 작성하면 되는지 입력하세요.

더보기

한 줄씩 개행하여 작성한다.

 

manager@example.com 계정을 reduser로 포워딩 설정하는 내용을 입력하세요.

더보기

manager@example.com reduser

 

manager@example.com 계정을 manager@external.com으로 포워딩 설정하는 내용을 입력하세요.

더보기

manager@example.com manager@external.com

 

포워딩 설정 내용을 반영하기 위해 어떤 작업을 해야하는지 입력하세요.

더보기

포워딩 수정은 별다른 작업없이 바로 메일 서비스에 반영된다.

 


 

가상유저

 

가상유저를 설정하기 위한 파일의 전체경로를 입력하세요.

더보기

/etc/mail/vertusertable

 

info@example.org의 가상 계정을 만들고 이를 org-manager에게 전달하는 내용을 입력하세요.

더보기

info@example.org org-manager

 

marketing@example.com의 가상 계정을 만들고 이를 marketer@external.com으로 전달하는 내용을 입력하세요.

더보기

marketing@example.com marketer@external.com

 

가상유저 설정을 적용하기 위한 명령어를 입력하세요.

더보기

$ makemap hash /etc/mail/vertusertable < /etc/mail/vertusertable

 


 

도메인 등록

 

메일 서버에서 사용할 도메인을 등록하는 파일의 전체 경로를 입력하세요.

더보기

/etc/mail/local-host-names

 

위 수정 사항을 반영하기 위한 명령어를 입력하세요.

더보기

$ systemctl restart sendmail


 

명령어

 

sendmail을 관리하기 위해 사용하는 옵션을 제외한 명령어 2개를 입력하세요.

더보기

sendmail, mailq