BigAdmin System Administration Portal
Sun Java System Messaging Server 6 2005Q4의 전자 메일 전달 동작
Print-friendly VersionPrint-friendly Version

Sun Java System Messaging Server 6 2005Q4의 전자 메일 전달 동작

Jeff Allison과 Ned Freed, 2006년 11월

이 기사에서는 Communications Express 인터페이스에서 현재 전자 메일 전달을 구현하는 방법뿐 아니라 전송 수준 전달 및 Sieve 언어 redirect를 비롯하여 Sun Java System Messaging Server 내의 전자 메일 전달 동작에 대해 다룹니다.

Messaging Server의 메일 전달 기능을 사용하면 사용자의 전자 메일을 해당 사용자의 기본 주소 외에 추가로 또는 이 주소 대신에 다른 주소로 전달할 수 있습니다. 이 기사에서도 논의되는 루핑 문제를 감지하고 해결하는 경우 Messaging Server의 메일 전달 구현을 이해하는 것은 중요합니다.

복잡한 메시징 시스템의 많은 부분과 마찬가지로 전달은 표면상에 드러난 것보다 훨씬 복잡합니다. 전달이 구현되는 방식을 선택함으로써 나타나는 동작은 처음에는 명백하지 않을 수 있습니다. 이 기사에서는 다양한 전달 옵션 및 설정에 대한 상세한 내용과 일부 복잡한 내용을 설명하고자 합니다.


전송 수준 전달 예

사용자 Alice(alice@example.com)가 다음과 같은 메시지를 사용자 Bob(bob@example.com)에게 보낸다고 가정합니다.

From: Alice 
To: Bob 
Subject: sample message subject
Date:  whenever
Content-type: text/plain
MIME-Version: 1.0

test message

이제 전송 수준 전달 메커니즘을 사용하여 이 메시지를 charlie@example.com으로 전달하면, 이 경우 수신자는 Bob이 아니라 Charlie가 됩니다. 메시지 헤더와 구조는 어떤 방식으로든 변경되지 않고 더 이상 추가되는 헤더는 없습니다. 하지만 메시지에 2가지 변경 내용이 표시됩니다. 첫 번째, Received: 필드의 for 절에는 수신자로 Bob이 아니라 Charlie가 나열됩니다. 두 번째, 최종 배달 중에 추가되는 original-recipient 필드에는 Charlie가 아니라 Bob이 나열됩니다.

예를 들어 BobmailDeliveryOption 설정은 forward로, mailForwardingAddresscharlie@example.com으로 지정하여 본인의 전자 메일이 Charlie로 전달되도록 설정하는 경우에 이러한 상황이 발생합니다. 예를 들어 Bob이 본인의 전자 메일이 Charlie로 전달되도록 설정하는 작업은 설정이 forwardmailDeliveryOption 속성과 charlie@example.com으로 지정된 mailForwardingAddress를 추가하여 LDAP 디렉토리의 사용자 항목 수준에서 수행됩니다.

이러한 종류의 전송 수준 전달에는 광범위한 검사 항목들이 있어 메시지 루프를 감지하고 방지할 수 있습니다. 따라서 본인의 고유 주소를 mailForwardingAddress로 지정하여 메시지를 Bob 본인에게 전달하는 것과 같은 작업은 즉시 감지되고 확인됩니다. Charlie에게 전달하는 사용자 BobBob에게 다시 전달하는 Charlie는 서로 비슷한 방법으로 확인됩니다. 실제로 Messaging Server의 루프 검사 로직은 단일 MTA(메시지 전송 에이전트)에서 사용할 수 있는 전달 정보에 내재해 있는 거의 모든 루프를 포착하고 다룹니다.

여러 시스템에서 전송 수준 전달과 관련된 루프는 감지되지 않을 수 있습니다. 하지만 Received: 필드는 각 홉에서 항상 추가되므로 이러한 루프는 Received: 필드를 카운트하여 감지할 수 있습니다. 이러한 카운트는 기본적으로 Messaging Server에서 수행됩니다. 그리고 Received: 필드 수가 설정 가능한 여러 제한 사항 중 하나라도 초과하면 메시지는 자동으로 보관됩니다. 이 작업을 통해 .HELD 파일로 표시되는 "밑줄이 그어진" 메시지를 정기적으로 검사해야 하는 사이트의 포스트마스터가 메시지에 관심을 기울이게 됩니다. 그런 다음 포스트마스터는 루프의 구성 요소가 무엇이고, 루프를 분할하기 위해 변경해야 할 것은 무엇인지 정확히 알기 위해 메시지의 Received: 필드를 살펴보기만 하면 됩니다.

.HELD 메시지를 검사하는 방법에 대한 자세한 내용은 Sun Java System Messaging Server 6 2005Q4 관리 설명서.HELD 메시지 진단 및 정리 섹션을 참조하십시오.


Sieve 전달 예

Sieve 언어 redirect를 사용하여 전달하는 방법은 전송 수준 전달 동작과 비슷하지만 엄밀히 말하자면 똑같지는 않습니다. MTA는 새 메시지 수신자를 만들고 이 메시지 수신자를 reprocess 채널로 안내하여 리디렉션 작업을 구현합니다. 이 경우 추가된 채널 홉이 있으며, 해당 메시지는 추가 Received: 필드까지 표시합니다.

Sieve 언어 스크립트는 매우 복잡하므로 이러한 루프 감지 분석은 실행할 수 없습니다. 즉, 스크립트 분석을 통해 감지될 수 없는 루프를 생성하는 Sieve 스크립트를 작성할 수 있습니다. 이는 Sieve 스크립트와 관련된 루프는 생성과 동시에 포착해야 함을 의미합니다. 정적 분석을 통해서는 찾을 수 없습니다. 하지만 redirectReceived: 필드를 추가하므로(실제로 MTA 수준 전달에서 추가되는 만큼의 두 배 추가) 리디렉션 루프를 포착하고 종료하는 작업은 어렵지 않습니다. 이러한 루프의 원인을 확인하는 작업이 더 어려울 수 있습니다. Sieve가 단순한 "무조건 여기서 전달"보다는 좀 더 복잡할 수 있기 때문입니다. 그럼에도 불구하고 Received: 필드에서 루프 발생시 수행한 조치에 대해 알릴 수 있으므로 보통 모든 작업이 어려운 것은 아닙니다. 다양한 로깅 옵션이 MTA에 있어 Sieve 작업을 기록할 수 있습니다. 이러한 옵션은 루프를 분해하는 데 매우 유용합니다.

Sieve에 대한 자세한 내용은 Sun Java System Messaging Server 6 2005Q4 관리 설명서Sieve 필터 지원을 참조하십시오.


전자 메일 루프 문제 해결 예

다음 예는 전자 메일 전달에 대한 문제를 이해하는 데 유용합니다. 사용자가 전자 메일 루프와 관련된 문제를 겪고 있다고 가정하고, 첫 번째 단계로 추가 헤더 필드를 메시지에 삽입합니다. 관련 표준을 통해 이 목적에 적합한 헤더가 정확히 정의됩니다(Resent- 필드). 메시지에 Resent- 필드를 추가하면 이 필드는 다음과 같은 메시지를 표시하여 Charlie에게 배달됩니다.

Resent-from: Bob 
Resent-to: Charlie 
Resent-date: whenever2
From: Alice 
To: Bob 
Subject: sample message subject
Date:  whenever1
Content-type: text/plain
MIME-Version: 1.0

test message

다른 방법으로는 비표준 필드를 사용하는 것입니다(예: Forwarded-by). 또한 어떤 방식으로든 제목 행에 태그를 지정할 수 있습니다. 문제는 이러한 기술 중 어느 것도 일반적으로 잘 작동하지 않는다는 것입니다. 많은 전자 메일 클라이언트 프로그램에서는 헤더 필드의 작은 서브세트만 살펴볼 수 있고, 이 외의 것은 살펴보기가 쉽지 않습니다. 그리고 제목 행의 태그 지정이 표시되면 메시지 스레딩과 같은 다른 작업에 영향을 미치게 됩니다. 임의의 전달 수를 처리하기 위해 메시지 태그 지정은 조정되지 않습니다. 실제로 전달 한 개만 수행되고 나면 문제가 발생합니다.

추가적인 문제로는 Messaging Server 2005Q1(6.2)에서 Sieve redirect 구현을 통해 추가 헤더를 전달된 메시지에 삽입할 수 없다는 점이 있습니다. 이 문제는 Messaging Server(Messaging Server 6.3)의 차후 릴리스에서 수정됩니다. addheader 및/또는 addtagredirect와 결합하고, Resent- 필드, Forward-by 헤더를 추가하거나 제목 행에 태그를 지정할 수 있습니다.

addheader 작업을 통해 현재 메시지에 헤더를 추가할 수 있습니다. 이 작업에서는 일반적인 field: content 형식의 헤더 필드 이름과 내용이 모두 포함되어 있는 단일 문자열 인수가 사용됩니다. addheader 확장자 이름은 require 절에서 지정할 수 있지만 필수 항목은 아닙니다.

Messaging Server 6.3 릴리스 및 후속 릴리스에서는 인터넷 초안 draft-ietf-sieve-editheader-02.txt에서 설명된 Sieve editheader 확장자가 지원됩니다. 이 초안은 현재 SIEVE IETF 작업 그룹에서 최종 승인 단계에 있습니다.

(현재) 비표준 addtag 작업을 통해 현재 메시지 제목 필드에 태그 문자열 접두어를 추가할 수 있습니다. 이 작업에서는 추가할 태그 문자열이 포함된 단일 문자열 인수가 사용됩니다. 제목 행은 태그가 이미 표시되어 있는지 확인하기 위해 검사됩니다. 이미 표시된 경우 수행할 작업은 없습니다. 태그는 필터 처리가 발생하고 나면 대기열 항목 이전까지 추가되지 않습니다. 이는 Sieve 필터 간 통신을 위한 수단으로 태그를 사용할 수 없음을 의미합니다.


Communications Express 및 Sieve

Communications Express 클라이언트에서는 Notify :echo라는 전달에 다른 Sieve 프리미티브를 사용합니다. Notify는 지정된 내용을 담은 완전히 새로운 메시지를 작성하고, 원래 메시지(":echo" 부분)는 선택적으로 첨부합니다. 사용되는 구성은 다음과 비슷합니다.

if header :matches "Subject" "*" {
    notify :method "email" :echo :options "charlie@example.com"
     "auto-forwarded-1:1" "This is an auto-forwarded message";
     stop;
  }

이 메커니즘이 사용되면 Charlie는 다음과 같은 메시지를 받습니다.

   From: Bob 
   To: Charlie 
   Subject: auto-forwarded-1:sample message subject
   Date: whenever2
   Content-type: multipart/mixed; boundary=a
   MIME-Version: 1.0

   --a
   content-type: text/plain

   This is an auto-forwarded message

   --a
   content-type: message/rfc822

   From: Alice 
   To: Bob 
   Subject: sample message subject
   Date:  whenever1
   Content-type: text/plain
   MIME-Version: 1.0

   test message

이 전달 방법에는 문제가 있습니다. 먼저 이 접근 방법으로는 더 이상 여러 유형의 루프를 감지할 수 없고 효과적으로 다룰 수 없습니다. 그 이유는 중첩된 메시지를 사용하면 대부분의 Received: 필드가 헤더 바깥쪽이 아니라 메시지 데이터 내부에 배치되기 때문입니다. 또한 인터넷 전자 메일 아키텍처는 이 방법이 메시지 중첩에 대한 적격 사용 사례라고 여기지 않으므로 중첩된 메시지에 "이 메시지는 실제로 중첩된 것이 아니며 간단한 메시지를 구조화하는 생소한 방식입니다."라고 알리는 레이블을 지정할 수 없습니다.

Subject: 필드에 Received: 필드 카운터 유형을 만들어 이러한 상황을 해결하려는 시도가 있었으나, 잘 해결되지 않습니다. 많은 항목이 Subject: 필드를 변경할 수 있고 이 정교한 로직 유형을 쉽게 분해할 수 있습니다. Received: 필드 수를 사용할 때 항상 폴백 기능을 원하는 것은 바로 이러한 이유 때문입니다. notify로는 이 상황을 해결할 수 없습니다.

하지만 알림 루프를 감지할 수 있는 또 다른 방법이 있습니다. 장기간 솔루션으로는 적절하지 않지만, redirect/addheader를 사용할 수 있는 때인 Messaging Server 6.3 릴리스로 업그레이드할 때까지 다음은 notify를 사용하여 알림 루프를 감지하는 것을 도와줍니다.

Sieve mime 루프 확장자를 사용하면 메시지에서 중첩 수준 수를 카운트하는 초기 루프 감지기에 연결할 수 있습니다. 기본 명령은 다음과 같습니다.

if header :mime :anychild :count "gt" :comparator
          "i;ascii-numeric" "MIME-Version" "20"
{
	loop detected
}

이 명령은 :mime :anychild로 인해 헤더 테스트가 단지 외부 헤더에 있는 필드가 아니라 중첩된 헤더 필드를 모두 검사하므로 작동합니다. 각 notify는 다른 중첩 수준과 다른 MIME-Version: 필드를 추가합니다. 결국 개수는 임계값을 초과하고, 루프를 감지할 수 있게 됩니다. 이 방법의 단점은 긍정 오류에 취약하다는 점입니다. 이에 대한 분명한 예로는 메시지 다이제스트가 들어 있는 메시지가 있습니다. 이러한 메시지에는 수십 개 또는 수백 개의 MIME-Version: 필드가 쉽게 포함될 수 있으며, 이로 인해 감지기를 조기에 가동시킵니다. 하지만 이러한 메시지 다이제스트 메시지는 거의 없습니다. 긍정 오류 외에도 올바른 캡슐화 종류를 사용하지 않는 일부 알림 구성자로 인한 부정 오류가 있습니다. 하지만 Sun의 notify 구현에서는 항상 올바른 캡슐화 종류를 사용하므로 이는 중요한 관심사가 아닙니다.


메일 전달에 대한 또 다른 접근 방법이 있습니까?

이 시점에서 물어볼 수 있는 명확한 질문은 위에서 논의한 접근 방법 외에 근본적으로 다른 가능한 전달 접근 방법이 있는지 여부입니다. 이 질문에 대한 대답은 '아니오'입니다. 근본적으로 다른 추가 접근 방법은 없습니다. 인터넷 전자 메일 메시지가 봉투, 헤더 및 본문 세 가지로 구성되어 있음을 고려해보면 이를 쉽게 이해할 수 있습니다. 위에서 설명한 세 가지 접근 방법은 봉투만 변경하고, 봉투와 헤더를 변경하고, 세 가지 모두를 변경하는 작업에 해당합니다. 변경할 수 있는 다른 요소는 없습니다.

이 기사에서 다뤘던 예로 돌아가서 루프가 클라이언트에 의해 생성된 Sieve 언어 스크립트에서 감지된 후 제품에 루프를 다루는 더 좋은 방법이 있을 경우 사용자가 이 방법이 더 효율적이라고 판단했다고 가정해봅시다. 사용자는 루프가 감지되면 포스트마스터에게 몇 가지 알림 종류를 보내는 솔루션을 제안합니다. 기준은 다음과 같습니다.

  1. 이 메일에는 포스트마스터가 문제를 진단하도록 허용하는 일부 정보가 포함되어야 합니다. 해당 정보에는 원래 메일과 적용되지 않은 메일 필터 규칙이 포함될 수 있습니다.
  2. 최종 사용자에게 전송된 메일에는 자동 전달되지 않은 메일이 포함되어 있고 어떤 규칙이 적용되지 않았는지 명시되어 있어야 최종 사용자가 발생하지 않은 사항을 정확히 알 수 있습니다.
  3. 허용되는 자동 전달 수는 수정할 수 있는 메일 서버 매개 변수여야 합니다.

이 요청을 살펴볼 때 포스트마스터에 무언가를 보내는 작업은 물론 notify를 사용하여 수행할 수 있으며 :echo는 원래 메시지를 알림에 포함시킵니다. 그러므로 (1) 항목 및 (2) 항목을 구현할 수 있습니다. (3) 항목은 생성되는 Sieve의 내용을 변경하는 매개 변수를 통해 구현할 수 있습니다. 하지만 매개 변수 변경은 Sieve가 이후에 변경될 때만 영향을 미칩니다. 디렉토리에서 후보 Sieve 스크립트를 검색하고 모두 변경하여 기존 Sieve에 대한 변경 작업을 수행해야 할 수 있습니다.

하지만 이러한 단계 중 하나라도 수행하면 전자 메일 라우팅의 가장 기본적인 규칙 중 하나를 위반하게 됩니다. 즉, 루프가 감지되면 추가 메일 메시지 보내기 작업을 시작하지 말아야 합니다. 다시 말해 이 요청은 다년간의 개발 경험을 토대로 메시징 모범 사례로 알고 있는 것과 완전히 어긋납니다. 루프가 감지될 때 가장 좋은 조치는 메시지에 밑줄을 긋고(Messaging Server에서는 메시지를 .HELD 파일로 만듦) 문제를 수정할 수 있는 사람이 이 메시지에 관심을 가지게 하는 것입니다.

또한 좀 더 이해하기 어려운 문제가 발생하기도 합니다. Messaging Server에서는 알림에 Sieve 규칙이 실행하거나 실행하지 않은 항목에 대한 표시기를 비롯하여 사용자가 원하는 것은 무엇이든 넣을 수 있지만 이렇게 하면 생각보다 훨씬 적은 작업이 수행됩니다. 문제는 사용자가 Sieve 구성을 정기적으로 변경하고, 이 변경이 발생하는 경우 알림에 이제 유효하지 않은 정보가 포함됨으로써 추적하는 데 좀 더 어려운 문제가 실제로 발생한다는 점입니다.

또한 루프가 만들어지고 루프 감지 로직이 트리거되어 그 결과 포스트마스터가 수많은 알림을 수신한다고 가정해보십시오. 이제 포스트마스터가 수행해야 할 작업은 무엇입니까? 명확한 대답은 루프를 수정하는 것입니다. 하지만 위에서 언급한 대로 알림은 바라는 만큼 문제를 격리하는 데 도움이 되지 않습니다. 대부분의 경우 루프 분해와 관련된 큰 문제는 루프를 제거하기 위해 변경해야 하는 항목이 아니라 루프가 존재하는 이유를 파악하지 못하는 것입니다.

루프가 이제 수정되었다고 가정해보십시오. 루프로 인해 손실된 메시지는 어떻습니까? 해당 메시지는 잘못된 메일함에 있습니다. 포스트마스터는 이러한 복사본을 찾고, 삭제하고, 복사본을 처음에 받았어야 했지만 받지 못한 사람에게 메시지를 다시 전송해야 합니다. 메시지를 제 위치에서 유지하는 것은 옵션이 아닙니다. 누군가가 메시지를 우연히 발견하고, 실제로 메시지를 그대로 두어야 할 경우임에도 실행해야 할 메시지라고 가정할 수 있기 때문입니다. 얻어야 할 메시지가 불필요하게 중복되는 것은 우선 사용자에게 전달되지 말아야 하는 메시지를 얻는 것과 별개의 문제입니다. 오류 상태의 메시지를 받은 사용자는 즉시 메시지를 실행할 수 있으므로 포스트마스터도 메시지가 루핑을 시작하면 거의 즉시 실행할 수 있어야 합니다. 물론 이 작업은 사실 그렇게 되기 힘듭니다.

notify :echo 사용으로 인한 문제의 대안은 이것을 사용하지 않고 대신 redirect+addheader/addtag를 사용하는 것입니다. 이렇게 하면 수반되는 모든 항목과 함께 기존 루프 감지 메커니즘이 다시 작업을 시작합니다. 메시지 구조는 더 이상 변경되지 않습니다.


전달에 대한 Communications Express의 접근 방법에 대한 추가 정보

Communications Express가 현재 redirect를 사용하는 필터 대신 전달을 수행하는 notify를 사용하는 필터를 생성한다는 사실은 다음 릴리스(Sun Java Communications Suite Release 5의 Messaging Server 6.3)에서 수정되도록 예정된 결함입니다.

한편, Communications Express에서 메일 루핑이 발생하고 있다면 MAX_NOTIFYS를 활성화하고(그 때문에 사이트가 증가하는 메일 루프에 취약하게 됨), 다음 릴리스에서 소프트웨어 업데이트에 의해 문제가 해결될 때까지 Communications Express에서 "잘못된" 전달 동작이 예상된다고 사용자에게 알리기보다는 전달이 작동되지 않는 상태로 유지하는 것이 좋습니다.


Unless otherwise licensed, code in all technical manuals herein (including articles, FAQs, samples) is provided under this License.


BigAdmin
  
 
BigAdmin Upgrade Hub