[GH-ISSUE #639] Regression v1.29.0, Mark all messages read fails with HTTP error 403 (Unauthorized) #401

Closed
opened 2026-03-15 14:15:11 +03:00 by kerem · 11 comments
Owner

Originally created by @fasterit on GitHub (Feb 7, 2026).
Original GitHub issue: https://github.com/axllent/mailpit/issues/639

$ curl 'https://mailpit/api/v1/messages'
-X PUT
-H 'Content-Type: application/json'
-H 'Authorization: Basic ...'
--data-raw '{"read":true}'
--> Unauthorised.

Works with mailpt v1.28.4.

Greets!
/DLange

Originally created by @fasterit on GitHub (Feb 7, 2026). Original GitHub issue: https://github.com/axllent/mailpit/issues/639 $ curl 'https://mailpit/api/v1/messages' \ -X PUT \ -H 'Content-Type: application/json' \ -H 'Authorization: Basic ...' \ --data-raw '{"read":true}' --> Unauthorised. Works with mailpt v1.28.4. Greets! /DLange
kerem closed this issue 2026-03-15 14:15:16 +03:00
Author
Owner

@axllent commented on GitHub (Feb 7, 2026):

I'm pretty sure this is user-error - because it's working perfectly fine for me. If your command is multi-line curl request, are you sure you're escaping the newlines with a \?

curl 'https://mailpit/api/v1/messages' \
  -X PUT \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Basic dXNlcjpwYXNz' \
  --data-raw '{"read":true}'
<!-- gh-comment-id:3865412823 --> @axllent commented on GitHub (Feb 7, 2026): I'm pretty sure this is user-error - because it's working perfectly fine for me. If your command is multi-line curl request, are you sure you're escaping the newlines with a `\`? ``` curl 'https://mailpit/api/v1/messages' \ -X PUT \ -H 'Content-Type: application/json' \ -H 'Authorization: Basic dXNlcjpwYXNz' \ --data-raw '{"read":true}' ```
Author
Owner

@fasterit commented on GitHub (Feb 7, 2026):

It is also broken from the mailpit UI.

Again, v1.28.4 doesn't have the bug but that may well be related to using Apache mod_proxy in front of it:

	# Mailpit forwarding
	<IfModule mod_proxy.c>
		<IfModule mod_proxy_http.c>
			ProxyRequests Off
			ProxyPass "/" "http://127.0.0.1:8025/"
			ProxyPassReverse "/" "http://127.0.0.1:8025/"

			# configure the websocket
			RewriteEngine on
			RewriteCond %{HTTP:Upgrade} websocket [NC]
			RewriteCond %{HTTP:Connection} upgrade [NC]
			RewriteRule ^/?(.*) "ws://127.0.0.1:8025/$1" [P,L]
		</IfModule>
	</IfModule>

... this snippet works with v1.28.4 and it fails (only for the PUT, mark all read case) in v1.29.0.

May be your new Multi-CORS code is causing that?

<!-- gh-comment-id:3865438138 --> @fasterit commented on GitHub (Feb 7, 2026): It is also broken from the mailpit UI. Again, v1.28.4 doesn't have the bug but that may well be related to using Apache mod_proxy in front of it: ```Apacheconf # Mailpit forwarding <IfModule mod_proxy.c> <IfModule mod_proxy_http.c> ProxyRequests Off ProxyPass "/" "http://127.0.0.1:8025/" ProxyPassReverse "/" "http://127.0.0.1:8025/" # configure the websocket RewriteEngine on RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteCond %{HTTP:Connection} upgrade [NC] RewriteRule ^/?(.*) "ws://127.0.0.1:8025/$1" [P,L] </IfModule> </IfModule> ``` ... this snippet works with v1.28.4 and it fails (only for the PUT, mark all read case) in v1.29.0. May be your new Multi-CORS code is causing that?
Author
Owner

@axllent commented on GitHub (Feb 7, 2026):

Right, I think you're correct. Ironically nginx does not have any issue - so this appears to be specific to apache. Let me see if I can work out why and I'll get back to you.

<!-- gh-comment-id:3865508851 --> @axllent commented on GitHub (Feb 7, 2026): Right, I think you're correct. Ironically nginx does not have any issue - so this appears to be specific to apache. Let me see if I can work out why and I'll get back to you.
Author
Owner

@fasterit commented on GitHub (Feb 7, 2026):

Cool, thanks @axllent. No rush.

<!-- gh-comment-id:3865540174 --> @fasterit commented on GitHub (Feb 7, 2026): Cool, thanks @axllent. No rush.
Author
Owner

@axllent commented on GitHub (Feb 7, 2026):

I've actually "solved" it - it is blocking now thanks to the new CORS implementation. In order to repurpose the CORS security for websockets, and make it far more flexible to allow for multiple domain names, I shifted the CORS blocking to the server, rather than relying on the client. The only time CORS blocking kicks in is when the connecting client sends the "Origin" header.

Now it seems an apache proxy adds an origin header for all proxied PUT & DELETE requests. Another thing I noted is that websockets (which would have probably already been broken from earlier versions). This means that according to Mailpit, you went to https://mailpit/, however that website is querying the API using http://127.0.0.1:8025/ - so CORS is blocking.

The only fix I can think of here is to set the --api-cors '*' in your Mailpit instance, which effectively disables CORS entirely, or if you know that mailpit will only be accessed via https://mailpit, then you could use --api-cors 'mailpit'.

Please let me know if that resolved the issue for you?

<!-- gh-comment-id:3865579247 --> @axllent commented on GitHub (Feb 7, 2026): I've actually "solved" it - it is blocking now thanks to the new CORS implementation. In order to repurpose the CORS security for websockets, and make it far more flexible to allow for multiple domain names, I shifted the CORS blocking to the server, rather than relying on the client. The only time CORS blocking kicks in is when the connecting client sends the "Origin" header. Now it seems an apache proxy adds an origin header for all proxied PUT & DELETE requests. Another thing I noted is that websockets (which would have probably already been broken from earlier versions). This means that according to Mailpit, you went to https://mailpit/, however that website is querying the API using `http://127.0.0.1:8025/` - so CORS is blocking. The only fix I can think of here is to set the `--api-cors '*'` in your Mailpit instance, which effectively disables CORS entirely, or if you know that mailpit will only be accessed via `https://mailpit`, then you could use `--api-cors 'mailpit'`. Please let me know if that resolved the issue for you?
Author
Owner

@fasterit commented on GitHub (Feb 7, 2026):

Hm, I have to think about the security implications and run some tests. May be localhost, 127.0.0.1, ::1 should be in the default to be allowed (thinking out loud)?

<!-- gh-comment-id:3865650777 --> @fasterit commented on GitHub (Feb 7, 2026): Hm, I have to think about the security implications and run some tests. May be localhost, 127.0.0.1, ::1 should be in the default to be allowed (thinking out loud)?
Author
Owner

@axllent commented on GitHub (Feb 8, 2026):

I thought about that too, but that exposes Mailpit to any malicious website: https://github.com/axllent/mailpit/security/advisories/GHSA-524m-q5m7-79mm

<!-- gh-comment-id:3865791312 --> @axllent commented on GitHub (Feb 8, 2026): I thought about that too, but that exposes Mailpit to any malicious website: https://github.com/axllent/mailpit/security/advisories/GHSA-524m-q5m7-79mm
Author
Owner

@fasterit commented on GitHub (Feb 9, 2026):

I think the best solution is to actually make Apache forward the original Host: header with ProxyPreserveHost On. That way Mailpit v1.29.0 does the right thing™ automatically.

It also works, alternatively, to set MP_API_CORS=mailpit as you suggested.

<!-- gh-comment-id:3874094418 --> @fasterit commented on GitHub (Feb 9, 2026): I think the best solution is to actually make Apache forward the original Host: header with [`ProxyPreserveHost On`](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypreservehost). That way Mailpit v1.29.0 does the right thing™ automatically. It also works, alternatively, to set `MP_API_CORS=mailpit` as you suggested.
Author
Owner

@axllent commented on GitHub (Feb 10, 2026):

Thanks @fasterit - that's a very good suggestion, much better than what I suggested. I have tested here and it works as expected, and still correctly blocks cross origin connections. I've updated the Mailpit documentation. Strange how this only seems to affect PUT, DELETE and websockets though, however regular GET and POST ajax requests work fine. Anyway, I'm not going to try understand why Apache does that... Thanks for your bug report!

<!-- gh-comment-id:3875206668 --> @axllent commented on GitHub (Feb 10, 2026): Thanks @fasterit - that's a very good suggestion, much better than what I suggested. I have tested here and it works as expected, and still correctly blocks cross origin connections. I've updated the [Mailpit documentation](https://mailpit.axllent.org/docs/configuration/proxy/#proxy-via-apache). Strange how this only seems to affect `PUT`, `DELETE` and websockets though, however regular GET and POST ajax requests work fine. Anyway, I'm not going to try understand why Apache does that... Thanks for your bug report!
Author
Owner

@kleinphi666 commented on GitHub (Feb 11, 2026):

I had this problem with nginx as well but solved it by adding proxy_set_header Host $host; in the 'configure the websocket' section.

<!-- gh-comment-id:3883084964 --> @kleinphi666 commented on GitHub (Feb 11, 2026): I had this problem with nginx as well but solved it by adding `proxy_set_header Host $host;` in the 'configure the websocket' section.
Author
Owner

@axllent commented on GitHub (Feb 13, 2026):

@kleinphi666 - you're right, I have this (well almost this) in my default nginx proxy config, namely: proxy_set_header Host $http_host. I will add this to the nginx docs in the near future when I return home.

<!-- gh-comment-id:3895580356 --> @axllent commented on GitHub (Feb 13, 2026): @kleinphi666 - you're right, I have this (well almost this) in my default nginx proxy config, namely: `proxy_set_header Host $http_host`. I will add this to the nginx docs in the near future when I return home.
Sign in to join this conversation.
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
starred/mailpit#401
No description provided.