디스커스에 미러링된 메일링 리스트에 대한 게시물의 답글이 어떻게 처리되는지와 관련하여 흥미롭고 잘 알려지지 않은 버그를 발견했습니다.
초기 이메일이 동시에 두 개의 메일링 리스트로 발송된 경우, 한 메일링 리스트에 대한 답글이 다른 메일링 리스트(독자층이 다른 곳)에 잘못 기록될 수 있다는 증거를 확보했습니다.
제 Gmail 주소로 구독된 A와 B라는 두 개의 메일링 리스트에 속해 있다고 가정해 보겠습니다. 두 리스트는 잠재적으로 다른 독자층을 가질 수 있습니다. 리스트 서버는 두 메일링 리스트의 수신자에게 메시지의 단일 사본을 보내지만, To: 헤더에는 해당 메시지가 동일한 이메일로 A와 B 리스트로 발송되었음을 나타냅니다. 이 이메일은 제 Gmail 주소로 도착하며, Gmail은 필터를 통해 listA@mydiscourse.org.uk로 사본을 전달합니다. 이때 Gmail은 To: 헤더의 두 리스트 중 하나를 선택합니다. Gmail은 A 리스트로 온 게시물을 listA@mydiscourse.org.uk로, B 리스트로 온 게시물을 listB@mydiscourse.org.uk로 전달하도록 설정되어 있습니다. 디스커스에는 두 개의 서로 다른 수신 미러링 이메일 주소(listA@mydiscourse.org.uk와listB@mydiscourse.org.uk)를 가진 두 개의 카테고리가 설정되어 있습니다.
리스트 서버와 Gmail이 단일 사본만 보내는 문제는 별개이며, 이 버그의 주제는 아닙니다.
여기까지는 모두 정상입니다(리스트 서버로부터 처음부터 이메일이 하나만 온 사실은 제외하고).
이제, B 메일링 리스트에만 속한 다른 사용자가 해당 이메일에 리스트 서버로 답글을 보냅니다. 리스트 서버는 그 메시지를 B 메일링 리스트의 모든 사람에게 발송합니다. 이 메시지는 To: 헤더에 B 리스트로 발송되었음을 나타내며 제 Gmail 주소로 도착합니다. Gmail은 이를 listB@mydiscourse.org.uk로 전달합니다.
따라서 A 리스트에 접근 권한이 있는 사람들에게 B 리스트 멤버의 게시물 내용이 노출됩니다!
디스커스가 이메일이 디스커스에 도달한 경로를 무시하고, 헤더의 메시지 ID 플래그를 기반으로 기록하여 수신 경로를 우회한다고 추정합니다.
A와 B로 발송된 원래 이메일에는 단일 메시지 ID가 포함되어 있으며, 이 메시지 ID만으로 기록이 이루어지는 것으로 추정됩니다.
원래 발신자가 A 리스트와 B 리스트로 두 개의 별도 이메일을 보냈다면, 두 메시지가 각각 고유한 메시지 ID를 가지므로 이 문제는 발생하지 않았을 것입니다.
제안하는 수정 사항: 카테고리가 메일링 리스트를 미러링하고 있으며, 헤더를 보면 디스커스의 다른 위치에 있는 게시물에 대한 답글인 것처럼 보이는 메시지가 미러링 주소를 통해 들어오는 경우, 답글이 다른 메일링 리스트와 연관된 카테고리에 들어가는 대신 예상되는 카테고리에 새 게시물을 생성해야 합니다(명확한 부모 게시물 없이).
내가 설명을 잘했는지 잘 모르겠습니다. 왜냐하면 Discourse가 게시물을 잘못된 카테고리에 넣는 이유를 이해할 수 없기 때문입니다. (우선순위가 있어야 할) 라우트를 보고 있는 것이 아니라 message-id만 보고 있는 것처럼 보입니다. 동시에 두 개의 메일링 리스트로 발송된 단일 이메일의 경우, message-id는 하나이지만 서로 독립적인 두 개의 배포 목록, 두 개의 'To: ’ 주소, 그리고 두 개의 'Reply-To: ’ 주소(각 메시지에 표시되는 주소는 발송된 리스트에 따라 다름)가 존재합니다.
만약 이것이 실제로 일어나고 있는 상황이라면, 누군가가 메일링 리스트 미러인 카테고리에서 주제를 다른 곳으로 이동시킨 후 메일링 리스트를 통한 답글이 계속 도착하게 된다면 어떻게 될까요? Discourse는 해당 답글들을 메일링 리스트와 연관된 카테고리에 추가할까요(원본 게시물이 이미 이동되었더라도)? 아니면 모든 답글이 마법처럼 주제가 이동된 카테고리에 모일까요?
Discourse는 동일한 message-id를 가지지만 'To: ’ 주소가 다른 두 개의 메시지를 동시에 두 개의 카테고리에 유지하는 상황을 처리할 수 있나요?
Discourse가 이를 어떻게 처리하든, Message-ID는 고유해야 합니다. 제 생각에는 리스트서버가 메일링 리스트에 메시지를 전송할 때 해당 메시지의 새로운 인스턴스를 생성하므로, 메시지 ID를 다시 작성해야 합니다.
또한, A 리스트와 B 리스트의 구성원 모두에게 원래 메시지가 적합할 수 있는데, 왜 B 리스트 구성원의 답장은 A 리스트 구성원에게 공개될 수 없는지 이해가 되지 않습니다. 대상 청중이 그렇게 다르다면, 왜 사용자는 동시에 두 리스트에 동일한 메시지를 보내는 것일까요?
아마도 이를 위한 좋은 기술적 해결책이 있을 수 있고, Discourse가 이를 올바르게 처리하도록 변경될 수도 있지만, 저는 36년 된 기술에서 이런 정말 기이한 경계 사례라고 생각합니다.
메시지가 동일하므로 메시지 ID가 하나라고 주장할 수 있습니다. 실제로 해당 예시에서 원포스터는 Gmail(메시지 ID를 할당하는 도구)에서 메시지를 작성했으며, 이는 동일한 서버의 두 개의 리스트서브(listserv) 주소로 전송되었습니다. 이는 드문 일이 아닙니다. 예를 들어, 관리자들과 임상 전문가들 각각이 별도의 메일링 리스트에 속해 있는 경우, 그들에게 공통으로 배포되는 뉴스 릴리스일 수 있습니다. 뉴스 릴리스에는 논의가 필요한 의학적 문제가 포함되어 있을 수 있으므로, 임상 전문가가 답장을 보낼 수 있습니다(To: 헤더에는 여전히 두 메일링 리스트가 언급되어 있지만, Reply-to: 주소는 임상 전문가 리스트로 설정되어 있을 것입니다). 마찬가지로, 관리자들은 뉴스에 대한 자신의 관점을 논의하고 싶을 수 있습니다. 그들은 답장을 보내고, 관련 Reply-to: 헤더는 관리자의 리스트를 반영하도록 사용될 것입니다. 만약 어떤 포스터가 To: 주소를 사용하여 '모두에게 답장’을 했다면, 해당 포스터가 멤버가 아닌 리스트에서 바운스(bounce) 메시지가 생성되었을 것입니다.
위와 같은 동작은 그다지 비일상적이지 않지만, Discourse가 메일링 리스트 미러로 사용될 때 이를 올바르게 처리하지 못하는 것으로 보입니다. 이는 포크된(forked) 답장들이 모두 원래의 메시지 ID에 고정되고, 해당 게시물이 처음 등장한 카테고리에 묶이기 때문입니다.
이 경우, 예를 들어 임상 전문가가 임상 전문가 리스트에 응답한 게시물이 Discourse의 메시지 파일링 방식 때문에 관리자의 리스트 미러에 표시되어, 관리자들이 임상 전문가들의 게시물을 볼 수 있게 될 수 있습니다.
해결책으로는, 수신 메시지의 To: 헤더에 있는 각 주소를 확인하여 각 카테고리 설정의 메일링 리스트 미러 주소와 일치하는지 검사하는 것입니다. 일치하는 경우, 해당 메시지의 사본을 각 일치하는 카테고리에 게시할 수 있으며, 게시물이 서로 다른 카테고리에 여러 사본으로 게시될 수도 있습니다. 그런 다음, 답장이 들어오면 현재와 마찬가지로 메시지 ID를 사용할 수 있지만, To: 줄이 해당 카테고리와도 일치할 때만 사용할 수 있습니다.
해결책 중 하나로, 메일 클라이언트가 생성한 원래 ID를 반영하면서 추가 식별자(예: Discourse가 이미 참조하는 메일링 리스트의 To: 주소)를 붙여 message-id를 다시 작성하는 옵션을 제공하는 것은 어떨까요? 이렇게 하면 메일링 리스트 B에서 들어온 게시물이 메일링 리스트 A의 게시물에도 존재하는 message-id 헤더를 참조하고 있을 경우, Discourse가 이를 올바르게 분류할 수 있을 것입니다.
예를 들어, 사용자가 두 개의 메일링 리스트 A와 B에 동시에 원본 이메일을 보내고, 고유한 message-id가 '1234567890gmail’이라고 가정해 보겠습니다.
Discourse는 일반 수신 주소로 전달된 두 개의 사본을 받게 됩니다. 첫 번째 메시지는 To: 주소가 리스트 A를 가리키므로 리스트 A 기준으로 분류되고, Discourse가 message-id 뒤에 추가 문자를 붙여 '1234567890gmailListA’로 만듭니다. 두 번째 메시지는 중복으로 판단되어 분류되지 않습니다. (이것이 현재 동작 방식이라고 생각합니다.)
리스트 B의 누군가가 리스트 B의 To: 주소를 사용하여 답장을 보냅니다. Discourse는 사본을 받고 '1234567890gmail’을 포함하는 in-reply-to 헤더를 발견합니다. Discourse는 이메일이 리스트 B를 반영하는 To: 줄을 가지고 들어왔으므로, 끝에 문자를 추가하여 in-reply-to 헤더를 '1234567890gmailListB’처럼 보이게 합니다. 그리고 더 이상 리스트 A에 분류된 메시지와 연결되어 있지 않으므로, 이를 올바른 카테고리에 있는 새로운 메시지로 분류합니다.
이 방식은 아카이브 이전에도 적용될 수 있습니다. 사용자가 여러 리스트에 동시에 메시지를 보낸 경우, 동일한 message-id가 여러 메일링 리스트에서 발견될 수 있기 때문입니다. 가져오기 시점에 모든 message-id 필드(및 in-reply-to)에 이름이 지정된 메일링 리스트와 연결된 고유 텍스트를 추가하여, 메시지가 인덱싱될 때 아카이브 간의 일종의 교차 간섭을 방지할 수 있습니다.