bug: incoming email feature fails #12436

Open
opened 2026-05-06 16:07:55 +02:00 by jogchum · 3 comments
jogchum commented 2026-05-06 16:07:55 +02:00 (Migrated from codeberg.org)

Can you reproduce the bug on the Forgejo test instance?

No, I can't try it on the test instance for some reason

Description

The incoming email feature fails to process email replies when the token in the reply-to address is lowercase. I only tested on my own self hosted instance (also on a local gitea instance, it has the same issue). That is why I set the first question to "no".

  • Forgejo generates reply-to addresses like: ⁠incoming+ABC123@example.com
  • Some email clients (confirmed with Hey email client) normalize email addresses to lowercase
  • The address becomes: ⁠incoming+abc123@example.com
  • Forgejo fails to decode the token with error: ⁠illegal base32 data at input byte 0

I think this happens because:

  • Tokens are base32-encoded (which uses uppercase A-Z and digits 2-7)
  • The decode function in ⁠services/mailer/token/token.go line 85 is case-sensitive
  • When the token is lowercased, base32 decoding fails

This potentially affects any email client that normalizes email addresses to lowercase.

As far as I understand Forgejo checks multiple headers for tokens (To, Delivered-To, and References), so this affects all token extraction paths.

Steps to reproduce:

  1. Configure incoming email feature
  2. Create an issue to trigger a notification
  3. Either: use Hey email client to reply, OR manually lowercase the token in the reply-to address
  4. Check logs for the error

Forgejo Version

15.0.1+gitea-1.22.0

How are you running Forgejo?

Running in Kubernetes using Helm chart forgejo-helm/forgejo version 17.0.1

Configuration: PostgreSQL database, Valkey (Redis) for cache/session/queue, Minio (Garage S3) for storage, incoming email via IMAP (imap.forwardemail.net)

Logs

I added some line numbers to the logging, the error is on line 5. It's actually the only log that gets through when sending an email in.

Logs with DEBUG level enabled
 1  2026/05/06 13:54:41 ...c/net/http/server.go:2286:ServeHTTP() [I] PING DATABASE postgresschema
 2  2026/05/06 13:54:41 ...eb/routing/logger.go:102:func1() [I] router: completed GET /api/healthz for [redacted]:36922, 200 OK in 2.2ms @ healthcheck/check.go:67(healthcheck.Check)
 3  2026/05/06 13:54:51 ...c/net/http/server.go:2286:ServeHTTP() [I] PING DATABASE postgresschema
 4  2026/05/06 13:54:51 ...eb/routing/logger.go:102:func1() [I] router: completed GET /api/healthz for [redacted]:54786, 200 OK in 2.2ms @ healthcheck/check.go:67(healthcheck.Check)
 5  2026/05/06 13:54:55 ...incoming/incoming.go:277:processMessages() [E] Error while processing incoming email[0]: illegal base32 data at input byte 0
 6  2026/05/06 13:54:59 ...eb/routing/logger.go:102:func1() [I] router: completed GET /metrics for [redacted]:46572, 200 OK in 29.0ms @ web/metrics.go:16(web.Metrics)
 7  2026/05/06 13:55:01 ...c/net/http/server.go:2286:ServeHTTP() [I] PING DATABASE postgresschema
 8  2026/05/06 13:55:01 ...eb/routing/logger.go:102:func1() [I] router: completed GET /api/healthz for [redacted]:59926, 200 OK in 1.9ms @ healthcheck/check.go:67(healthcheck.Check)

Database

PostgreSQL

### Can you reproduce the bug on the Forgejo test instance? No, I can't try it on the test instance for some reason ### Description The incoming email feature fails to process email replies when the token in the reply-to address is lowercase. I only tested on my own self hosted instance (also on a local gitea instance, it has the same issue). That is why I set the first question to "no". - Forgejo generates reply-to addresses like: ⁠incoming+ABC123@example.com - Some email clients (confirmed with Hey email client) normalize email addresses to lowercase - The address becomes: ⁠incoming+abc123@example.com - Forgejo fails to decode the token with error: ⁠`illegal base32 data at input byte 0` I think this happens because: - Tokens are base32-encoded (which uses uppercase A-Z and digits 2-7) - The decode function in ⁠services/mailer/token/token.go line 85 is case-sensitive - When the token is lowercased, base32 decoding fails This potentially affects any email client that normalizes email addresses to lowercase. As far as I understand Forgejo checks multiple headers for tokens (To, Delivered-To, and References), so this affects all token extraction paths. Steps to reproduce: 1. Configure incoming email feature 2. Create an issue to trigger a notification 3. Either: use Hey email client to reply, OR manually lowercase the token in the reply-to address 4. Check logs for the error ### Forgejo Version 15.0.1+gitea-1.22.0 ### How are you running Forgejo? Running in Kubernetes using Helm chart forgejo-helm/forgejo version 17.0.1 Configuration: PostgreSQL database, Valkey (Redis) for cache/session/queue, Minio (Garage S3) for storage, incoming email via IMAP (imap.forwardemail.net) ### Logs I added some line numbers to the logging, the error is on line 5. It's actually the only log that gets through when sending an email in. <details> <summary>Logs with DEBUG level enabled</summary> ``` 1 2026/05/06 13:54:41 ...c/net/http/server.go:2286:ServeHTTP() [I] PING DATABASE postgresschema 2 2026/05/06 13:54:41 ...eb/routing/logger.go:102:func1() [I] router: completed GET /api/healthz for [redacted]:36922, 200 OK in 2.2ms @ healthcheck/check.go:67(healthcheck.Check) 3 2026/05/06 13:54:51 ...c/net/http/server.go:2286:ServeHTTP() [I] PING DATABASE postgresschema 4 2026/05/06 13:54:51 ...eb/routing/logger.go:102:func1() [I] router: completed GET /api/healthz for [redacted]:54786, 200 OK in 2.2ms @ healthcheck/check.go:67(healthcheck.Check) 5 2026/05/06 13:54:55 ...incoming/incoming.go:277:processMessages() [E] Error while processing incoming email[0]: illegal base32 data at input byte 0 6 2026/05/06 13:54:59 ...eb/routing/logger.go:102:func1() [I] router: completed GET /metrics for [redacted]:46572, 200 OK in 29.0ms @ web/metrics.go:16(web.Metrics) 7 2026/05/06 13:55:01 ...c/net/http/server.go:2286:ServeHTTP() [I] PING DATABASE postgresschema 8 2026/05/06 13:55:01 ...eb/routing/logger.go:102:func1() [I] router: completed GET /api/healthz for [redacted]:59926, 200 OK in 1.9ms @ healthcheck/check.go:67(healthcheck.Check) ``` </details> ### Database PostgreSQL
Gusted commented 2026-05-07 20:24:25 +02:00 (Migrated from codeberg.org)

The straightforward fix would be to upper-case it before it goes into verification. Marking as good first issue.

The straightforward fix would be to upper-case it before it goes into verification. Marking as good first issue.
abidos commented 2026-05-07 23:03:27 +02:00 (Migrated from codeberg.org)

Hey @Gusted! I would love to work on it! pls assign it to me!

Hey @Gusted! I would love to work on it! pls assign it to me!
Gusted commented 2026-05-07 23:11:31 +02:00 (Migrated from codeberg.org)

@abidos the comment enough is to indicate you're working on it. We don't really use the assignee feature otherwise.

@abidos the comment enough is to indicate you're working on it. We don't really use the assignee feature otherwise.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sleepy/forgejo#12436
No description provided.