요약
RSET는 아직 완료되지 않은 SMTP 메시지를, 더 오래 지속되는 세션 안에서 버릴 수 있는 트랜잭션으로 만들었습니다. 발신자, 수신자, 데이터가 모두 지워지지만 서버는 연결을 닫아서는 안 됩니다.- 이 구분 덕분에 복구가 명시적인 프로토콜 이벤트가 되었습니다. 리셋은 무엇을 버렸는지 확인해 줄 뿐, 이미 완료된 메시지를 되돌리거나 더 넓은 보안 컨텍스트를 지우거나 무엇이 배달되었는지 증명하지 않습니다.
상태를 바꾼 수신자
클라이언트가MAIL FROM을 보낸 뒤 두 개의RCPT TO명령을 보냈다고 상상해 봅시다. 첫 번째 수신자는 수락되었습니다. 두 번째는 거부되었습니다. 클라이언트의 애플리케이션은 메시지가 두 수신자 모두에게 가거나 아무에게도 가지 않기로 결정합니다.
거부된 명령이 수락된 명령을 지우지는 않았습니다. 서버는 여전히 역방향 경로와 하나의 순방향 경로를 들고 있을 수 있습니다. 이 상태에서DATA를 보내면 애플리케이션이 이미 포기한 트랜잭션을 계속 이어가게 됩니다. 즉시 다른MAIL을 보내면 이전 트랜잭션이 아직 열려 있는 동안 새 트랜잭션을 시작하려는 시도가 됩니다. TCP 연결을 닫으면 모호성은 사라지지만, 쓸 수 있는 연결까지 버리고 계획의 지역적 변경을 전송 실패로 바꿉니다.
RSET는 클라이언트에게 더 좁은 연산을 제공했습니다. 즉, 이 메일 트랜잭션을 포기하라는 것입니다. 긍정 응답은 서버가 트랜잭션 로컬 상태를 지웠고 다음 단계를 깨끗이 시작할 준비가 되었다는 뜻입니다.
이 작은 메커니즘은 큰 아키텍처적 아이디어를 담고 있습니다. 연결, SMTP 세션, 메일 트랜잭션은 서로 관련이 있지만 같은 것이 아닙니다.
리셋은 처음부터 있었습니다
RFC 821은 이미 1982년에RSET을 기술했습니다. 저장된 발신자, 수신자, 메일 데이터는 모두 폐기되어야 했고, 버퍼와 상태 테이블은 비워져야 했으며, 수신 측은 OK 응답을 반환해야 했습니다. 같은 사양은 하나의 세션이 0개 이상의 메일 트랜잭션을 담을 수 있다고 말했습니다.
이 짝이 중요합니다. SMTP는 하나의 대화에서 여러 메시지를 옮기도록 설계되었으므로, 대화 전체를 쓸모없다고 선언하지 않고 한 메시지를 포기할 방법이 필요했습니다. 이 명령은 드문 오류 처리를 위한 후보가 아니었습니다. 트랜잭션 경계를 복구 가능하게 만든 연산이었습니다.
RFC 821은 또한 이전 명령이 오류를 받았다는 이유만으로 전송 채널을 닫지 말라고 양측에 지시했습니다. 연결이 조기에 끊긴 경우에도 서버는 대기 중인 트랜잭션을 취소하되 이미 완료된 트랜잭션은 보존해야 했습니다. 그때부터 프로토콜은 채널, 완료되지 않은 시도, 이미 수락된 메시지라는 세 개의 기록을 분리했습니다.
응답도 경계의 일부입니다
클라이언트 측 큐를 비우는 것만으로는 부족합니다. 서버가 클라이언트가 더 이상 쓰지 않으려는 수신자를 수락했을 수 있고, 클라이언트는 서버의 버퍼를 들여다볼 수 없습니다. 재사용은 상대가 리셋을 인지했음을 확인한 뒤에야 안전해집니다.
RFC 5321은 이 확인을 정확하게 규정합니다. 인수 없는RSET은250 OK를 받습니다. 명령은 언제라도 내릴 수 있습니다. 열린 트랜잭션이 없다면 사실상 아무 일도 하지 않고(no-op), 트랜잭션 상태가 존재하면 발신자, 수신자, 메일 데이터가 폐기됩니다. 가장 중요한 것은, 서버가RSET을 받았다는 이유로 연결을 닫아서는 안 된다는 점입니다. 채널을 닫는 일은QUIT의 몫입니다.
이 교환에서의250은 배달 확인증이 아닙니다. 메시지 앞부분이 아니라 리셋 동작을 승인한 것입니다. 모든 내부 바이트가 안전하게 지워졌다고 약속하지도 않습니다. 프로토콜에서 보이는 상태를 확립할 뿐입니다. 즉, 버려진 트랜잭션이 다음 트랜잭션을 지배해서는 안 된다는 것입니다.
잊어버리고도 남는 것
“모든 버퍼와 상태 테이블이 비워진다”는 말을 듣고RSET을 세션 전체의 기상양으로 여기고 싶은 유혹이 있습니다. SMTP의 주변 규칙들은 더 작은 범위를 보여줍니다.
TCP 연결은 열려 있습니다. 서버는 인사말을 다시 반복하지 않습니다. 클라이언트는 수신자 집합 하나를 포기하기 위해 모든 확장을 다시 발견할 필요가 없습니다. TLS는 제거되지 않습니다. 인증된 신원은 익명이 되지 않습니다. 속도 제한, 감사 기록, 남용 관찰은 트랜잭션 로컬 메일 데이터로 정의되지 않습니다.
그래서 RFC 5321은 이후에 수락된EHLO가RSET과 동일한 형식상 트랜잭션 리셋 효과를 가지지만, 인사말과 기능 협상 작업까지 수행하므로 보통 비용이 더 크다고 설명합니다. 둘 다 열린 메시지를 중단할 수 있지만, 세션 상태가 왜 바뀌었는지에 대한 서로 바꿔 쓸 수 없는 설명입니다.
STARTTLS는 더 넓은 경계를 보여줍니다. RFC 3207은 양측이 TLS 핸드셰이크에 성공한 뒤 TLS 이전에 학습한 지식을 폐기하고EHLO로 기능을 다시 확립하도록 요구합니다. 보안 컨텍스트가 바뀌었기에 프로토콜은 의도적으로 오래된 지식이 그 경계를 넘어가는 것을 거부합니다.RSET이 유용한 이유는 버려지는 대부분의 메시지가 그런 넓은 재협상을 정당화하지 않기 때문입니다.
트랜잭션은 시간을 거슬러 되돌아가지 않습니다
리셋은 현재 완료되지 않은 트랜잭션에 적용됩니다. 이미 성공적으로 마무리된 트랜잭션을 철회하지는 않습니다.
RFC 5321은 메일 트랜잭션을 시작 명령, 하나 이상의 수신자 명령, 콘텐츠 전송으로 기술합니다. 하나의 세션은 그런 트랜잭션을 0개 이상 담을 수 있습니다. 최종 콘텐츠가 수락되면 메시지는 완료된 트랜잭션에 속합니다. 이후의 리셋은 세션을 다음 메시지를 위한 준비 상태로 만들 수 있지만, 앞선 수락을 비수락으로 바꿀 수는 없습니다.
이 한계는 지속 연결에 대한 위험한 해석을 막습니다. 세션은 그 위에서 보내진 모든 메시지를 아우르는 데이터베이스 트랜잭션이 아닙니다. 완료된 각 메시지는 자신의 수락 결과를 가집니다. 리셋은 살아 있는 봉투를 취소할 뿐, 역사를 다시 쓰지 않습니다.
더 빨라진 대화가 경계를 더 선명하게 만들었습니다
명령 파이프라이닝 덕분에 클라이언트는 각 줄 이후 기다리지 않고 선택한 SMTP 명령을 보낼 수 있게 되었습니다. RFC 2920은RSET, 발신자 명령,RCPT TO가 하나의 명령 그룹 안에 들어가는 것을 허용합니다. 한 메시지의 마지막 콘텐츠와 다음 메시지를 위한 리셋/새 발신자 시퀀스가 한 그룹을 공유하는 것까지 허용합니다.
이런 겹침이 트랜잭션 경계를 녹이지는 않습니다. 오히려 응답 대응 관계를 필수로 만듭니다. 모든 명령에는 여전히 순서대로 응답이 있고, 클라이언트는 그 전부를 추적해야 합니다. 최종 콘텐츠가 실패했는지, 리셋이 실패했는지, 새 발신자가 거부되었는지는 서로 다른 세 가지 결과입니다.
따라서 빠른 클라이언트는 로컬 버퍼를 비우고 서버도 같은 경계를 넘었다고 가정할 수 없습니다. 어느 응답이 이전 콘텐츠를 확인했는지, 어느 응답이 리셋을 확인했는지, 어느 응답이 다음 봉투를 열었는지 알아야 합니다.
불확정 청크에서의 복구
CHUNKING 확장은 정리 역할을 더 두드러지게 만들었습니다. RFC 3030은 콘텐츠가 하나 이상의BDAT청크로 도착할 수 있게 합니다. 특정 시퀀스 오류 —BDAT LAST이후의 다른 청크, 한 트랜잭션 안에서DATA와BDAT의 혼용, 트랜잭션 상태를 불확정으로 남기는 실패한 청크 — 가 발생하면 이후 명령을 계속하기 전에RSET이 요구됩니다.
여기서 리셋은 의례가 아닙니다. 부분 청크와 그 봉투가 더 이상 살아 있는 메시지에 속하지 않는다는 것을 양측에 알려 줍니다. 같은 세션이 이후 제대로 프레이밍된 메시지를 운반할 수 있지만, 깨끗한 트랜잭션 경계가 확인된 뒤에만 가능합니다.
인증은 반대 규칙을 따릅니다. RFC 4954는 열린 메일 트랜잭션 동안의AUTH를 금지하고503으로 거부할 것을 요구합니다. 신원은 하나의 봉투보다 넓은 범위를 가지므로, 프로토콜은 클라이언트가 발신자-수신자-데이터 시퀀스 중간에 새 인증 이벤트를 끼워 넣지 못하게 합니다.
이 역사는 범위가 한정된 복구의 교훈입니다
네트워크 프로토콜은 흔히 두 가지 조잡한 방법으로 복구합니다. 오류를 무시하고 양쪽이 여전히 동의하기를 바라거나, 연결 전체를 버리는 것입니다.RSET은 그 사이의 유용한 공간을 차지합니다. 버려도 되는 상태를 이름 붙이고 상대에게 새 경계를 확인하라고 요청합니다.
이 설계가 작동하는 이유는 그 약속이 제한적이기 때문입니다. 완료되지 않은 메시지는 잊을 수 있습니다. 대화는 계속될 수 있습니다. 완료된 메시지는 완료된 채로 남습니다. 보안과 기능 컨텍스트는 다른 명령이 바꾸지 않는 한 유지됩니다. 다음 봉투는 이전 봉투의 발신자, 수신자 또는 부분 콘텐츠를 물려받지 않고 시작됩니다.
SMTP는 상태를 무해하게 만들지 않았습니다. 상태를 나눌 수 있게 만들었습니다.
출처
- RFC 821 — Simple Mail Transfer Protocol
- RFC 5321 — Simple Mail Transfer Protocol
- RFC 2920 — SMTP Service Extension for Command Pipelining
- RFC 3030 — SMTP Service Extensions for Transmission of Large and Binary MIME Messages
- RFC 4954 — SMTP Service Extension for Authentication
- RFC 3207 — SMTP Service Extension for Secure SMTP over TLS
- IANA — Simple Mail Transfer Protocol registries
회원 브리핑
프로필 심층 컨텍스트
올바른 멤버십 등급으로 로그인하면 전체 브리핑과 출처 노트를 볼 수 있습니다.
Strategic Circle 전용
Strategic Circle
모든 독자에게 공개됩니다. 가입 후 로그인하면 프로필 브리핑를 열람할 수 있습니다.
Strategic Circle 가입하기Leadership Alliance 전용
Leadership Alliance
자격을 갖춘 IP 자산 소유자 및 운영진을 위한 콘텐츠입니다. 로그인하면 Leadership Alliance 브리핑을 열람할 수 있습니다.
Leadership Alliance 가입하기





