이유 없는 Email::Receiver::InvalidPost 오류

Got a few mailing lists mirrored over at Mailing Lists - Tor Project Forum

We recently noticed a few messages were not being mirrored from the Mailman3 mailing list to the forum.

The email rejection logs show these emails having encountered a Email::Receiver::InvalidPost error.

The error message logged is either of those two:

We’re sorry, but your email message to [“tor-relays@lists.torproject.org”] (titled [tor-relays] authority bandwidth measurements and latency) didn’t work.

Reason:

Access Denied

If you can correct the problem, please try again.

or:

We’re sorry, but your email message to [“tor-relays@lists.torproject.org”] (titled [tor-relays] Re: webtunnel bridges for the telegram distributor) didn’t work.

Reason:

Something has gone wrong. Perhaps this topic was closed or deleted while you were looking at it?

If you can correct the problem, please try again.

I can’t find anything wrong with these messages from looking at the headers, although in some instances, the extracted body as logged only contains the mailing list footer, or in another instance, it’s a bunch of gibberish characters like there was some decoding glitch.

I’ve tried to reproduce this issue using a test mailing list and test category but was unsuccessful. Any help debugging this would be appreciated.

1개의 좋아요

is “accept email from anonymous accounts” enabled in each category settings, and please could you send Discourse email log (slightly redacted if possible)

1개의 좋아요

Yes, I can confirm that this setting is enabled.

and please could you send Discourse email log (slightly redacted if possible)

Is things something I need to extract from the container or the host? We also process mail via the mail-receiver container. Or do you want the logs that are exposed in the Web UI (eg. /admin/email-logs/rejected)?

Did it come from Exchange?

Sometimes Microsoft Exchange will send out garbage if it’s misconfigured to think it’s talking to… I’m not sure - another Exchange server? Something else within its own infrastructure?

You can look at the raw mail from the Discourse console with e.g.:

mid = 'message-id from the log'
puts IncomingEmail.find_by(message_id: mid).raw

This shows the raw email that Discourse received. For example, this message body I just pulled out of our incoming rejection list really is garbage:

This is a multi-part message in MIME format.
--=====003_Dragon855807841081_=====
Content-Type: text/plain;
 charset=utf-8
Content-Transfer-Encoding: base64

7bgir+m+vzzIDCLE0mDmZrfIXvvmXjY=

--=====003_Dragon855807841081_=====
Content-Type: text/html;
 charset=utf-8
Content-Transfer-Encoding: base64

LP/0L4tqmfZizO0DCDDE10uOzMZqzSHDjq04SLPaBjibLVHz+V94m1M45NDN
55aM8SMIf9XY4EFjP9CCFz+ojfmJqmubaz+bjrzmubw+bjWTiGSuLg==

--=====003_Dragon855807841081_=====--

as the parts don’t decode to valid text.

2개의 좋아요

both would be grand. If you use PuTTy SSH you can extract the container logs, and you could snippet the Discourse UI. You can’t search for words in the photo easily though, to redact them​:face_exhaling:

I was able to extract two mails with the full headers. One MUA is Apple Mail and the other is Claws Mail.

I’d be happy to forward those to someone’s private email for debugging, so we avoid pasting it all over the Internet.

In think in both instances it’s likely Discourse that’s not parsing the email content correctly.

For the record, this is still a problem. Discourse regularly drops mailing list messages from various senders with the `Email::Receiver::InvalidPost` error, for reasons I can’t figure out.

If you click on the error in the logs, does it show why in the bounce reason?

e.g.:

If you click on the error in the logs, does it show why in the bounce reason?

Those messages come in two flavors:

We're sorry, but your email message to ["tor-relays@lists.torproject.org"] (titled [tor-relays] Re: abuse report from relays in family 7EAAC49A7840D33B62FA276429F3B03C92AA9327) didn't work.

Reason:

Something has gone wrong. Perhaps this topic was closed or deleted while you were looking at it?

If you can correct the problem, please try again.

I can confirm that no such thing (topic closed or deleted) has happened in these instances.

Some other times, the Reason is simply `Access Denied`.

Edit: the messages are the same as I described in my original post.

lavamind님, 안녕하세요 - 오래된 스레드를 다시 올리는 것이 죄송하지만, 디버깅을 더 깊이 진행하기 전에 먼저 확인하고 싶었습니다.

현재(2025년 말~2026년 초 기준) 메일링 리스트 미러링 시 Email::Receiver::InvalidPost 거부 오류가 여전히 발생하고 있나요?

발생 중이라면 다음 사항에 대한 간단한 스냅샷을 공유해 주실 수 있을까요?

  • 대략적인 발생 빈도 (예: 매일/매주, 메시지 비율)
  • 거부된 이메일의 "Reason"이 여전히 주로 "Access Denied"인지, 아니면 "topic closed/deleted"인지
  • 하나의 리스트/카테고리에서만 발생하는지, 여러 곳에서 발생하는지

여전히 발생하고 있다는 것을 확인하면, 최근 실패 사례 1건에 대한 최소한의 진단 정보(Message-ID + 해당 저장된 원본 이메일 등)를 수집하는 단계로 넘어갈 수 있습니다.

죄송할 것 없습니다. 이 문제를 조사해 주셔서 매우 기쁩니다.

lavamind님, 안녕하세요. 오래된 스레드를 다시 건드려 죄송합니다. 디버깅을 더 깊이 들어가기 전에 먼저 확인하고 싶어서 말씀드립니다.

현재(2025년 말 / 2026년 초 기준) 메일링 리스트 미러링에서 Email::Receiver::InvalidPost 거부 오류가 여전히 발생하고 있습니까?

네, 문제가 여전히 발생하고 있습니다.

발생 빈도가 대략 어느 정도인지 (예: 매일 / 매주, 메시지 수 대비 비율)

정확한 빈도를 파악하기는 어렵지만, 주당 최소 몇 건의 메시지가 영향을 받고 있으며, 대략 메시지 수의 5~10% 정도일까요? 일부 발신자가 에러 로그에 과다하게 나타나는 것 같아, 완전히 무작위로 발생하는 것 같지는 않습니다.

거부된 이메일의 "Reason"이 여전히 주로 "Access Denied"인지, 아니면 "topic closed/deleted"인지

여전히 두 가지가 혼재되어 있습니다.

하나의 리스트/카테고리만 영향을 받는 건지, 여러 개인 건지

주로 tor-relays 카테고리가 영향을 받고 있습니다. 이 리스트는 우리가 미러링하는 다른 리스트들과 달리 여러 발신자로부터 정기적으로 입력을 받으며, 다른 리스트들보다 트래픽이 훨씬 많습니다.

여전히 발생하고 있는지 확인되면, 최근 실패 사례 하나에 대한 최소 진단 정보(메시지 ID + 저장된 원본 이메일 등) 수집으로 넘어갈 수 있습니다.

이 최근 스레드를 살펴볼 수 있습니다. Mailman 아카이브에는 5개의 메시지를 받았다고 표시되어 있지만, 포럼 미러 토픽에는 게시물이 3개만 있습니다. 거부 로그에는 이 토픽에 대해 InvalidPost 오류가 3건 기록되어 있습니다(이상하게도 2건은 동일한 발신자로부터 온 것이며), 모두 거부 사유로 “Something has gone wrong. Perhaps this topic was closed or deleted while you were looking at it?”(문제가 발생했습니다. 이 토픽을 보고 계신 동안 닫히거나 삭제되었을 수 있습니다?)라고 표시됩니다.

lavamind님, 정말 유용한 데이터 포인트를 주셔서 감사합니다. 특히 "Mailman 아카이브에는 5개, 포럼 토픽에는 3개"라는 구체적인 스레드를 근거로 삼을 수 있어 더욱 도움이 됩니다.

주당 여러 번(대략 메시지의 5~10%) 이런 현상을 목격하고 계시고, 이번 사고에서는 반바운스(bounce) 이유가 일관되게 오해의 소지가 있는 “토픽 닫힘/삭제” 변형으로 표시되고 있으므로, 다음 최선의 단계는 실패한 메시지 하나를 끝에서 끝까지(end-to-end) 캡처하여 Discourse가 무엇을 하려 했는지 확인하는 것입니다.


해당 미러 토픽과 관련된 3개의 거부된 이메일 중 하나에 대해, 다음 내용을 가져와 주실 수 있을까요?

  1. /admin/email-logs/rejected에서 해당 사고에 대한 InvalidPost 행 중 하나를 열고 다음을 복사하세요:

    • Message-ID
    • 날짜/시간
    • 행에 표시된 (마스크 처리된) To / From / Subject
    • 전체 반바운스 이유 텍스트 (표시된 그대로)
  2. Rails 콘솔(Discourse 앱 컨테이너 내부)에서 Discourse가 저장한 원본 이메일을 추출하세요:

@supermathie 님, 원본(raw)을 가져오기 위한 표준 위치가 여전히 IncomingEmail인가요? 그리고 InvalidPost 디버깅을 위해 이와 함께 필요한 다른 것이 있을까요?

mid = "<거부된 이메일 로그의 Message-ID를 붙여넣으세요>"
ie  = IncomingEmail.find_by(message_id: mid)

puts ie&.raw
  1. 동일한 Message-ID에 대한 쌍을 이루는 EmailLog 속성도 가져오세요 (이것은 Discourse가 이를 답글로 처리했는지 새 토픽으로 처리했는지, 그리고 어떤 토픽/카테고리 ID를 해석했는지를 보여주는 경우가 많습니다):
mid = "<위와 동일한 Message-ID>"

log = EmailLog.where(message_id: mid).order(created_at: :desc).first
pp log&.attributes&.slice(
  "id",
  "email_type",
  "to_address",
  "from_address",
  "subject",
  "post_id",
  "topic_id",
  "user_id",
  "status",
  "bounce_error_code",
  "bounce_key",
  "created_at"
)

왜 이 세 가지인가요?

  • IncomingEmail.raw는 메일이 변형되어 도착했거나, 이상하게 인코딩되었거나, 푸터만 있는 경우와 Discourse가 “잘못된” MIME 부분을 선택한 경우를 구별해 줍니다.
  • EmailLog는 Discourse가 무엇을 시도했는지(새 토픽인지 답글인지, 해석된 토픽/카테고리 ID 등)를 알려줍니다.
  • 거부된 이메일 UI 행은 우리가 동일한 사고를 보고 있는지 확인하고, 운영자가 보는 내용을 보존해 줍니다.

개인정보 보호가 우려된다면, raw 내부의 주소와 메시지 본문 텍스트는 마스킹 처리하셔도 무방합니다. 하지만 다음 내용은 유지해 주세요:

  • MIME 헤더 (Content-Type, boundaries, charset, Content-Transfer-Encoding)
  • 멀티파트 구조 (어떤 부분이 존재하는지 볼 수 있도록)
  • Message-ID 및 기본 라우팅 헤더 (필요하다면 도메인은 마스킹 처리 가능)

실패한 Message-ID 하나 + IncomingEmail.raw + EmailLog 슬라이스를 확보하면, 이것이 무엇인지 빠르게 판단할 수 있을 것입니다:

  • 답글 키 / 토픽 라우팅 불일치,
  • 권한 엣지 케이스,
  • 또는 이메일 파싱 / MIME 부분 선택 / 디코딩 실패.

매우 상세한 안내를 해주셔서 감사합니다!

이 메시지가 메일링 리스트 토픽으로 전송된 것에 초점을 맞춰 보겠습니다.

거절된 게시글 로그의 인시던트 헤더는 다음과 같습니다:

Message-ID: <20260103080033.5f6d8f90@dorfdsl.de>
Date: Sat, 03 Jan 2026 08:00:33 +0100
From: Marco Moock via tor-relays <tor-relays@lists.torproject.org>
To: tor-relays@lists.torproject.org
Subject: [tor-relays] Re: Questions about running an exit relay

전체 거절 사유 텍스트는 다음과 같습니다:

We're sorry, but your email message to ["tor-relays@lists.torproject.org"] (titled [tor-relays] Re: Questions about running an exit relay) didn't work.

Reason:

Something has gone wrong. Perhaps this topic was closed or deleted while you were looking at it?

If you can correct the problem, please try again.

Mailman에서 Discourse로 전송된 이메일의 평문 기록(IncomingEmail)은 여기에서 확인하실 수 있습니다(이미 공개된 데이터가 아닌 것은 포함되지 않았다고 생각하지만, 아무튼 해당 링크가 결국 만료되도록 설정해 두었습니다).

불행히도 EmailLog를 추출하려는 제 시도는 어떤 결과도 내지 못했습니다. 해당 메시지에 대해 Discourse에 그런 기록이 없는 것 같습니다.

Thanks @lavamind - this is excellent (Message-ID + rejection text + a copy of what Discourse stored).

Also: my bad on the EmailLog ask - it’s very plausible (and maybe expected) that there’s no EmailLog row for an inbound rejection like this. EmailLog is primarily for outgoing mail, whereas inbound mail lives in IncomingEmail (which you’ve already pulled). @supermathie can you confirm I’m not sending folks down the wrong path here?

Given we do have the IncomingEmail, could you paste the metadata fields from that same record? That should give us the “what did Discourse try to do?” context I was hoping to get from EmailLog.

In Rails console:

# @supermathie sanity-check: for inbound InvalidPost debugging, is IncomingEmail metadata the right next thing to collect?

mid = "<20260103080033.5f6d8f90@dorfdsl.de>"
ie  = IncomingEmail.find_by(message_id: mid)

pp ie&.attributes&.slice(
  "id",
  "message_id",
  "from_address",
  "to_addresses",
  "cc_addresses",
  "subject",
  "created_at",
  "user_id",
  "post_id",
  "topic_id",
  "error"
)

# optional: if you’re comfortable, this is often useful too
# (it shows what Discourse extracted as the body vs what it stored raw)
pp ie&.attributes&.slice("raw", "cooked")

(If raw/cooked are huge, feel free to omit them - you’ve already shared the raw.)

Why these fields matter:

  • topic_id / post_id (if present) tells us whether Discourse resolved this as a reply/new post and what it targeted.
  • user_id tells us which staged/real user Discourse mapped the sender to (permissions / “Access Denied” cases).
  • error is often more specific than the generic “topic closed/deleted” bounce text.

If those attributes show topic_id/post_id resolution pointing at the mirror topic, then the likely next step is to work out why the receiver decided it was invalid (empty extracted body, MIME decoding, permissions mismatch, reply-key mismatch, etc). If it shows no topic/post resolution at all, we focus on routing headers / reply detection.

And again - thanks for the paste link. Having a single, concrete failing Message-ID like this is exactly what we needed to stop guessing.

네, 맞습니다. 그리고 동의합니다 - 수신된 내용, Discourse가 생성할 수 있었던 연관 관계, 그리고 hopefully 다음 단계를 나타내 줄 것입니다.

1개의 좋아요

IncomingObject의 메타데이터 필드는 다음과 같습니다.

{"id"=>9785,
"message_id"=>"20260103080033.5f6d8f90@dorfdsl.de",
"from_address"=>"mm@dorfdsl.de",
"to_addresses"=>"tor-relays@lists.torproject.org",
"cc_addresses"=>"",
"subject"=>"[tor-relays] Re: Questions about running an exit relay",
"created_at"=>2026-01-03 07:03:04.639775000 UTC +00:00,
"user_id"=>10477,
"post_id"=>nil,
"topic_id"=>nil,
"error"=>"Email::Receiver::InvalidPost"}

원본(raw)/처리된(cooked) 콘텐츠에 관해서는, 헤더를 포함한 전체 이메일은 raw 속성에만 포함되어 있습니다. cooked 속성은 해당 객체에 존재하지 않습니다.

이를 Email::Receiver.new(rawmessage).select_body로 처리하면 다음과 같은 결과가 반환됩니다:

=> ["", "", 2]

따라서 현재 발생하고 있는 문제는 Discourse가 메시지 본문으로 빈 plain/text 부분을 잘못 선택하고 있는 것 같으며, 아마도 아래 부분일 것입니다:

--Sig_/gizYC_1dGsAzUHvksdaMIe2
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit


이것은 잘못된 게시물이 됩니다.

이에 대해 조사를 좀 더 진행해야 하며, 아마도 이를 테스트 케이스로 사용하게 될 것입니다.

메일은 다음과 같은 구조를 가지고 있습니다:

* #<Mail::Part:39500, Multipart: false, Headers: <MIME-Version: 1.0>, <Content-Type: text/plain; charset=us-ascii>, <Content-Transfer-Encoding: 7bit>, <Content-Disposition: inline>, <Content-ID: <6958bf289b75c_b28a46298091029@forum-01-app.mail>>>
  "___…tor-relays 메일링 리스트…"
* #<Mail::Part:39520, Multipart: true, Headers: <Content-Type: multipart/signed; boundary="Sig_/gizYC_1dGsAzUHvksdaMIe2"; micalg=pgp-sha256; protocol="application/pgp-signature">, <Content-Transfer-Encoding: 7bit>>
  * #<Mail::Part:39540, Multipart: false, Headers: <Content-Type: text/plain; charset=US-ASCII>, <Content-Transfer-Encoding: quoted-printable>>,
    "On 02.01.2026…"
  * #<Mail::Part:39560, Multipart: false, Headers: <Content-Type: text/plain; charset=UTF-8>, <Content-Transfer-Encoding: 7bit>>,
    ""
  * #<Mail::Part:39580, Multipart: false, Headers: <Content-Type: text/plain; charset=US-ASCII>, <Content-Transfer-Encoding: quoted-printable>>,
    "On 02.01.2026…"
  * #<Mail::Part:39600, Multipart: false, Headers: <Content-Type: text/plain; charset=UTF-8>, <Content-Transfer-Encoding: 7bit>>,
    ""
  * #<Mail::Part:39620, Multipart: false, Headers: <Content-Type: text/plain; charset=US-ASCII>, <Content-Transfer-Encoding: quoted-printable>>,
    "On 02.01.2026…"
  * #<Mail::Part:39640, Multipart: false, Headers: <Content-Type: text/plain; charset=UTF-8>, <Content-Transfer-Encoding: 7bit>>,
    ""
  * #<Mail::Part:39660, Multipart: false, Headers: <Content-Type: text/plain; charset=US-ASCII>, <Content-Transfer-Encoding: quoted-printable>>,
    "On 02.01.2026…"
  * #<Mail::Part:39680, Multipart: false, Headers: <Content-Type: application/pgp-signature>, <Content-Description: Digitale Signatur von OpenPGP>>,
    PGP 서명
  * #<Mail::Part:39700, Multipart: false, Headers: <Content-Type: application/pgp-signature>, <Content-Transfer-Encoding: 7bit>, <Content-Description: Digitale Signatur von OpenPGP>>,
    PGP 서명
  * #<Mail::Part:39720, Multipart: false, Headers: <Content-Type: application/pgp-signature>, <Content-Transfer-Encoding: 7bit>, <Content-Description: Digitale Signatur von OpenPGP>>]
    PGP 서명

(네, 실제 콘텐츠, 빈 콘텐츠, 그리고 PGP 서명이 각각 3개씩 있습니다)

첫 번째 text/plain 부분은 메일링 리스트 소프트웨어에 의해 추가되며, 다음과 같은 모습입니다:

_______________________________________________
tor-relays 메일링 리스트 -- tor-relays@lists.torproject.org
해지하려면 tor-relays-leave@lists.torproject.org으로 이메일을 보내세요

Discourse(실제로는 .text_part를 통한 mail gem)가 메시지의 내용으로 선택하는 것이 바로 이것입니다:

> puts mail.text_part.to_s
MIME-Version: 1.0
Content-Type: text/plain;
 charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Content-ID: <6958bf289b75c_b28a46298091029@forum-01-app.mail>

_______________________________________________
tor-relays 메일링 리스트 -- tor-relays@lists.torproject.org
해지하려면 tor-relays-leave@lists.torproject.org으로 이메일을 보내세요

그리고 이것은 서명이 생략된 빈 본문으로 취급됩니다.

메일링 리스트에 의해 추가된 이 거의 빈 부분이 없었다면, Discourse는 게시글의 내용으로 다음과 같은 내용을 추출했을 것입니다:

> We received a court order to preserve the data on the system and were
> forbidden from informing the system owner, which was awkward since
> they had informed the system owner...

어떤 데이터를 요청했나요?

> Since then I've always run my exit on a separate system on it's own
> IP so if there were a legal demand to turn over "the system" it would
> really only be that system. I'm not a lawyer but I don't think docker
> provides enough isolation for that.

릴레이를 꺼달라고 거부할 수 있나요?
그렇다면 다른 IP로 새로운 "시스템"을 운영할 수 있습니다.

(아래는 생략된 부분)

On 02.01.2026 18:46 Jon via tor-relays <tor-relays@lists.torproject.org> wrote:

-- 
감사합니다
Marco

스팸은 abfall1767375998@stinkedores.dorfdsl.de로 보내주세요

여기서 Discourse의 메일 처리에 큰 하자를 찾기 어렵습니다 - 책임을 물을 필요가 있다면, 저는 실제로는 맨 앞에 빈 콘텐츠를 추가하는 메일링 리스트 소프트웨어부터 시작할 것입니다. 그것은 실제 메시지 이후인 끝에 위치하는 것이 더 적절했을 것입니다.

Mail gem에서는 이것이 작동했을 것이고, 메일 클라이언트에서도 더 잘 보였을 것입니다 - Thunderbird에서 처음 수신된 모습은 다음과 같습니다:

그리고 제 “수정” 버전 (test-fixed.eml.txt (14.3 KB))
메일링 리스트 서명을 맨 위가 아닌 맨 아래로 배치한 것입니다:

특정 IncomingEmail에 대해 게시글 내용으로 선택되었을 내용을 보고 싶다면, 다음을 실행하여 확인할 수 있습니다:

Email::Receiver.new(IncomingEmail.find(INCOMING_EMAIL_ID).raw).select_body

해당 목록의 (인간) 구독자에게 연락을 취해 보았고, 일부 헤더를 필터링한 후 그들의 MUA(메일 사용자 에이전트)에서 원시 메시지 본체가 어떻게 보이는지 확인했습니다:

Subject: [tor-relays] Re: Questions about running an exit relay
List-Id: "support and questions about running Tor relays (exit, non-exit,
 bridge)" <tor-relays.lists.torproject.org>
Archived-At: 
 <https://lists.torproject.org/mailman3/hyperkitty/list/tor-relays@lists.torproject.org/message/OAX7EO72GLXS4KPKUG7QSG7EOAR2WYVA/>
List-Archive: 
 <https://lists.torproject.org/mailman3/hyperkitty/list/tor-relays@lists.torproject.org/>
List-Help: <mailto:tor-relays-request@lists.torproject.org?subject=help>
List-Owner: <mailto:tor-relays-owner@lists.torproject.org>
List-Post: <mailto:tor-relays@lists.torproject.org>
List-Subscribe: <mailto:tor-relays-join@lists.torproject.org>
List-Unsubscribe: <mailto:tor-relays-leave@lists.torproject.org>
From: Marco Moock via tor-relays <tor-relays@lists.torproject.org>
Reply-To: Marco Moock <mm@dorfdsl.de>
Content-Type: multipart/mixed; boundary="===============8958541500975114832=="

--===============8958541500975114832==
Content-Type: multipart/signed; boundary="Sig_/gizYC_1dGsAzUHvksdaMIe2";
 protocol="application/pgp-signature"; micalg=pgp-sha256

--Sig_/gizYC_1dGsAzUHvksdaMIe2
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: quoted-printable

On 02.01.2026 18:46 Jon via tor-relays
<tor-relays@lists.torproject.org> wrote:

> We received a court order to preserve the data on the system and were
> forbidden from informing the system owner, which was awkward since
> they had informed the system owner...

Which data did they request?

> Since then I've always run my exit on a separate system on it's own
> IP so if there were a legal demand to turn over "the system" it would
> really only be that system. I'm not a lawyer but I don't think docker
> provides enough isolation for that.

Can they deny you to turn the relay off?
If so, you could then operate a new "system" on another IP.

--=20
kind regards
Marco

Send spam to abfall1767375998@stinkedores.dorfdsl.de

--Sig_/gizYC_1dGsAzUHvksdaMIe2
Content-Type: application/pgp-signature
Content-Description: Digitale Signatur von OpenPGP

-----BEGIN PGP SIGNATURE-----

iQJPBAEBCAA5FiEEpXefSZn9R6zNZtTQE76RLz2tRfAFAmlYvpEbFIAAAAAABAAO
bWFudTIsMi41KzEuMTEsMiwyAAoJEBO+kS89rUXw8kgP/2jkrwfSWHY6EY4WJjn6
EDEqT00pgpwEn9ZpUqLTreS3/ocfHC4g29HIsxpJcj/bH+hNAx96HEz9YmC4JfEt
LDjYc6D+5NBBFQGy0vaJ/LXLQc63CRE/yySSOYxFBZK+uMytNHoZDTjhfRroICbQ
guoO7A4/VuYrGAzCWQkBUmnBjj2LJhuLDW84ObMXhA/EuNy5FIAqyLZxoGmFEfvu
We5d0Hr3+wihzyrgGiG4u8UGFOyL+/PC11CFQyQ0j03cBzhZ5PVdtkqPNHauAcjQ
Gt/HQmaOSGKq0VODRjiHAe5TuRtV6jOfUNgS1Q2vB4FKYmeDQb82ooNfOiJWy3ey
Jpwgg700ppqgZUclpMPlzxKwi2dT/PSO6yYuy+G5sfa0Hxmn5DsQaiSPMTiEP2WC
NwAENYIuHeQOHWiS8B3oVSRW/naLzkmpfChFnTKGsrhLqKQc/iuvv639aHwg9BP7
YEbWbdpFpIU36czfxoTcDYDR1e4JLWryEFKIgo4TIaz4t17NmkxjXB6dHZKLLAdU
AT6LmL6mOTaXe9ewD9pf9Vf2nG0RGVJyZRUDmFzfU0Rx2qi7KdcmmRpZg/2QtJeA
Pmrv8NFuFEL0BrhTvo7C60m+gjLaXPNClgKEN0vkEzjLp/ZKjI9FslP61xUMg8lQ
3xT/HTkNt9uNH2ziBMXLK+5c
=0Euf
-----END PGP SIGNATURE-----

--Sig_/gizYC_1dGsAzUHvksdaMIe2--

--===============8958541500975114832==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
tor-relays mailing list -- tor-relays@lists.torproject.org
To unsubscribe send an email to tor-relays-leave@lists.torproject.org

--===============8958541500975114832==--

중복이 없으며, 각 부분은 올바른 순서로 배치되어 있습니다. 이것이 Mailman이 목록 구독자에게 실제로 전송하는 내용과 더 유사할 것이라고 예상합니다. 그렇지 않다면, 대다수의 사람들이 푸터가 맨 위에 있는 메시지를 받게 될 텐데, 그렇다면 아마도 그 문제에 대해 언급이 있었을 것입니다.

그래서 이제 처리 파이프라인의 다른 부분에서 메시지 본체에 영향을 미치고 있는 것이 있는지 궁금합니다. 우리의 Discourse 서버는 수신된 이메일을 먼저 Postfix로 처리하며, Postfix는 mail-receiver 컨테이너로 전달하도록 구성됩니다. 이 컨테이너는 다시 Discourse 컨테이너로 전달합니다.

아! 이 정보를 바탕으로 다시 조사해 보았는데… 결국 우리 쪽 문제였습니다.

위에서 게시하신 원본 이메일을 확인해 보니, IncomingEmail.raw가 실제로는 원본 이메일을 저장하지 않는다는 것을 발견했습니다. 우리는 먼저 Email::Cleaner로 이를 변환(munge)하고 있었습니다.

(미안합니다. 그동안 우리가 이 데이터를 신뢰할 수 있다고 생각했고, 과거에는 실제로도 그랬습니다)

이것은 Ruby의 mail gem의 문제인 것 같습니다… 이 라이브러리가 메시지를 다시 출력할 때 메일 메시지의 부분 순서를 재배열하기 때문입니다:

[1] pry(main)> m = File.open('test.eml').read;
[2] pry(main)> Mail.new(m).parts
=> [
  #<Mail::Part:39680, Multipart: true, Headers: <Content-Type: multipart/signed; boundary="Sig_/gizYC_1dGsAzUHvksdaMIe2"; protocol="application/pgp-signature"; micalg=pgp-sha256>>,
  #<Mail::Part:39700, Multipart: false, Headers: <MIME-Version: 1.0>, <Content-Type: text/plain; charset="us-ascii">, <Content-Transfer-Encoding: 7bit>, <Content-Disposition: inline>>
 ]
[3] pry(main)> Mail.new(Mail.new(m).to_s).parts
=> [
  #<Mail::Part:39720, Multipart: false, Headers: <MIME-Version: 1.0>, <Content-Type: text/plain; charset=us-ascii>, <Content-Transfer-Encoding: 7bit>, <Content-Disposition: inline>, <Content-ID: <6966b4914df79_31d5b1d38126@mars.mail>>>,
  #<Mail::Part:39740, Multipart: true, Headers: <Content-Type: multipart/signed; boundary="Sig_/gizYC_1dGsAzUHvksdaMIe2"; micalg=pgp-sha256; protocol="application/pgp-signature">, <Content-Transfer-Encoding: 7bit>>
]

이것이 문제를 일으킵니다:

[38] pry(main)> puts Email::Receiver.new(m).select_body[0];
> We received a court order to preserve the data on the system and were
> forbidden from informing the system owner, which was awkward since
> they had informed the system owner...

Which data did they request?

> Since then I've always run my exit on a separate system on it's own
> IP so if there were a legal demand to turn over "the system" it would
> really only be that system. I'm not a lawyer but I don't think docker
> provides enough isolation for that.

Can they deny you to turn the relay off?
If so, you could then operate a new "system" on another IP.

[39] pry(main)> puts Email::Receiver.new(Mail.new(m).to_s).select_body[0];
«no output»
차이점 상세 정보

test.eml: 제공된 원본 메시지
test-rubyparsed.eml: ruby로 파싱된 후 문자열로 변환된 메시지
test-pythonparsed.eml: python으로 파싱된 후 문자열로 변환된 메시지

--- test.eml	2026-01-13 15:58:18.769489410 -0500
+++ test-rubyparsed.eml	2026-01-13 16:11:17.767312268 -0500
@@ -1,25 +1,46 @@
+Date: Tue, 13 Jan 2026 16:07:21 -0500
+From: Marco Moock via tor-relays <tor-relays@lists.torproject.org>
+Reply-To: Marco Moock <mm@dorfdsl.de>
+Message-ID: <6966b40914be8_31d5b1d38719@mars.mail>
 Subject: [tor-relays] Re: Questions about running an exit relay
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="===============8958541500975114832=="
+Content-Transfer-Encoding: 7bit
 List-Id: "support and questions about running Tor relays (exit, non-exit,
  bridge)" <tor-relays.lists.torproject.org>
-Archived-At: 
- <https://lists.torproject.org/mailman3/hyperkitty/list/tor-relays@lists.torproject.org/message/OAX7EO72GLXS4KPKUG7QSG7EOAR2WYVA/>
-List-Archive: 
- <https://lists.torproject.org/mailman3/hyperkitty/list/tor-relays@lists.torproject.org/>
+Archived-At: <https://lists.torproject.org/mailman3/hyperkitty/list/tor-relays@lists.torproject.org/message/OAX7EO72GLXS4KPKUG7QSG7EOAR2WYVA/>
+List-Archive: <https://lists.torproject.org/mailman3/hyperkitty/list/tor-relays@lists.torproject.org/>
 List-Help: <mailto:tor-relays-request@lists.torproject.org?subject=help>
 List-Owner: <mailto:tor-relays-owner@lists.torproject.org>
 List-Post: <mailto:tor-relays@lists.torproject.org>
 List-Subscribe: <mailto:tor-relays-join@lists.torproject.org>
 List-Unsubscribe: <mailto:tor-relays-leave@lists.torproject.org>
-From: Marco Moock via tor-relays <tor-relays@lists.torproject.org>
-Reply-To: Marco Moock <mm@dorfdsl.de>
-Content-Type: multipart/mixed; boundary="===============8958541500975114832=="
+
+
+--===============8958541500975114832==
+MIME-Version: 1.0
+Content-Type: text/plain;
+ charset=us-ascii
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline
+Content-ID: <6966b40914ae9_31d5b1d38641@mars.mail>
+
+_______________________________________________
+tor-relays mailing list -- tor-relays@lists.torproject.org
+To unsubscribe send an email to tor-relays-leave@lists.torproject.org
 
 --===============8958541500975114832==
-Content-Type: multipart/signed; boundary="Sig_/gizYC_1dGsAzUHvksdaMIe2";
- protocol="application/pgp-signature"; micalg=pgp-sha256
+Content-Type: multipart/signed;
+ boundary="Sig_/gizYC_1dGsAzUHvksdaMIe2";
+ micalg=pgp-sha256;
+ protocol="application/pgp-signature"
+Content-Transfer-Encoding: 7bit
+
 
 --Sig_/gizYC_1dGsAzUHvksdaMIe2
-Content-Type: text/plain; charset=US-ASCII
+Content-Type: text/plain;
+ charset=US-ASCII
 Content-Transfer-Encoding: quoted-printable
 
 On 02.01.2026 18:46 Jon via tor-relays
@@ -39,7 +60,8 @@
 Can they deny you to turn the relay off?
 If so, you could then operate a new "system" on another IP.
 
---=20
+-- =
+
 kind regards
 Marco
 
@@ -47,6 +69,7 @@
 
 --Sig_/gizYC_1dGsAzUHvksdaMIe2
 Content-Type: application/pgp-signature
+Content-Transfer-Encoding: 7bit
 Content-Description: Digitale Signatur von OpenPGP
 
 -----BEGIN PGP SIGNATURE-----
@@ -69,14 +92,5 @@
 
 --Sig_/gizYC_1dGsAzUHvksdaMIe2--
 
---===============8958541500975114832==
-Content-Type: text/plain; charset="us-ascii"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Content-Disposition: inline
-
-_______________________________________________
-tor-relays mailing list -- tor-relays@lists.torproject.org
-To unsubscribe send an email to tor-relays-leave@lists.torproject.org
-
 --===============8958541500975114832==--
+
--- test.eml	2026-01-13 15:58:18.769489410 -0500
+++ test-pythonparsed.eml	2026-01-13 16:19:30.385608544 -0500
@@ -1,10 +1,8 @@
 Subject: [tor-relays] Re: Questions about running an exit relay
 List-Id: "support and questions about running Tor relays (exit, non-exit,
  bridge)" <tor-relays.lists.torproject.org>
-Archived-At: 
- <https://lists.torproject.org/mailman3/hyperkitty/list/tor-relays@lists.torproject.org/message/OAX7EO72GLXS4KPKUG7QSG7EOAR2WYVA/>
-List-Archive: 
- <https://lists.torproject.org/mailman3/hyperkitty/list/tor-relays@lists.torproject.org/>
+Archived-At: <https://lists.torproject.org/mailman3/hyperkitty/list/tor-relays@lists.torproject.org/message/OAX7EO72GLXS4KPKUG7QSG7EOAR2WYVA/>
+List-Archive: <https://lists.torproject.org/mailman3/hyperkitty/list/tor-relays@lists.torproject.org/>
 List-Help: <mailto:tor-relays-request@lists.torproject.org?subject=help>
 List-Owner: <mailto:tor-relays-owner@lists.torproject.org>
 List-Post: <mailto:tor-relays@lists.torproject.org>

다음 이슈를 열었습니다:

3개의 좋아요