Unexplained Email::Receiver::InvalidPost errors

Got a few mailing lists mirrored over at https://forum.torproject.org/c/mailing-lists/23

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.

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

1 Like

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 Likes

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😮‍💨

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.

Hi lavamind - sorry to bump an old thread, but I wanted to check in first before we go any deeper on debugging.

Are you still seeing the Email::Receiver::InvalidPost rejects on the mailing list mirroring as of now (late 2025 / early 2026)?

If yes, could you share a quick snapshot of:

  • roughly how often it happens (e.g. daily / weekly, % of messages)
  • whether the rejected-email “Reason” is still mainly “Access Denied” vs “topic closed/deleted”
  • whether it’s affecting one list/category or multiple

Once we confirm it’s still occurring, we can move on to collecting the minimum set of diagnostics for a single recent failure (Message-ID + the corresponding stored raw email, etc.).

No need to apologize, I’m very happy you’re looking into this.

Hi lavamind - sorry to bump an old thread, but I wanted to check in first before we go any deeper on debugging.

Are you still seeing the Email::Receiver::InvalidPost rejects on the mailing list mirroring as of now (late 2025 / early 2026)?

Yes, the problem is still occurring.

roughly how often it happens (e.g. daily / weekly, % of messages)

The frequency is difficult to pin down exactly, but the problem affects at least several messages per week, ballpark figure maybe somwehere between 5 to 10% of messages? Some senders seem to be overrepresented in the error logs, so at least it doesn’t look totally random.

whether the rejected-email “Reason” is still mainly “Access Denied” vs “topic closed/deleted”

It’s still a mix of the two.

whether it’s affecting one list/category or multiple

It’s affecting mainly the tor-relays category, but this list receives regular input from multiple senders contrary to the other lists which we mirror, which receive much lower traffic.

Once we confirm it’s still occurring, we can move on to collecting the minimum set of diagnostics for a single recent failure (Message-ID + the corresponding stored raw email, etc.).

We could look into this recent thread. Mailman’s archive indicates it received 5 messages, but the forum mirror topic only has 3 posts in it. The rejection logs contains 3 InvalidPost errors for this topic (2 from the same sender, stangely) and for all of them the rejection reason shown is “Something has gone wrong. Perhaps this topic was closed or deleted while you were looking at it?”

Thanks lavamind - that’s a really helpful data point, especially having a concrete “Mailman archive shows 5, forum topic shows 3” thread to anchor on.

Given you’re seeing this several times per week (ballpark 5-10% of messages) and that, for this incident, the bounce reason is consistently the misleading “topic closed/deleted” variant, the best next step is to capture one failed message end-to-end so we can see what Discourse thought it was doing.


For one of the 3 rejected emails associated with that mirror topic, could you grab the following:

  1. From /admin/email-logs/rejected, open one of the InvalidPost rows for that incident and copy:

    • the Message-ID
    • the date/time
    • the (redacted) To / From / Subject shown in the row
    • the full bounce reason text (as displayed)
  2. From the Rails console (in the Discourse app container), extract the raw email Discourse stored:

@supermathie is IncomingEmail still the canonical place to fetch the raw, and is there anything else you’d want alongside it for InvalidPost debugging?

mid = "<paste the Message-ID from the rejected email log>"
ie  = IncomingEmail.find_by(message_id: mid)

puts ie&.raw
  1. Also pull the paired EmailLog attributes for the same Message-ID (this often reveals whether Discourse treated it as a reply vs a new topic, and what topic/category IDs it resolved):
mid = "<same Message-ID as above>"

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"
)

Why this trio?

  • IncomingEmail.raw tells us if the mail arrived malformed / oddly encoded / footer-only, vs Discourse choosing the “wrong” MIME part.
  • EmailLog tells us what Discourse attempted (new topic vs reply, resolved topic/category ids, etc).
  • the rejected-email UI row confirms we’re looking at the same incident and preserves what operators see.

If privacy is a concern, feel free to redact addresses and any message body text inside raw, but please keep:

  • MIME headers (Content-Type, boundaries, charset, Content-Transfer-Encoding)
  • the multipart structure (so we can see which parts exist)
  • the Message-ID and basic routing headers (you can redact domains if needed)

Once we have one failing Message-ID + IncomingEmail.raw + the EmailLog slice, we should be able to tell quickly whether this is:

  • a reply-key / topic-routing mismatch,
  • a permissions edge case,
  • or an email parsing / MIME-part selection / decoding failure.