mirror of
https://github.com/axllent/mailpit.git
synced 2026-04-26 00:35:51 +03:00
[GH-ISSUE #434] CORS problem when using /api/view #279
Labels
No labels
awaiting feedback
bug
docker
documentation
enhancement
github_actions
invalid
pull-request
question
stale
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/mailpit#279
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @baiomys on GitHub (Feb 1, 2025).
Original GitHub issue: https://github.com/axllent/mailpit/issues/434
HI.
Is it possible to preprocess HTML content to do JS analog of
for external links ?
When showing HTML content in IFRAME external links fail if not preprocessed, but it's not an option when using cross-domain IFRAME. Prohibited by CORS.
Thanks.
@axllent commented on GitHub (Feb 2, 2025):
Hi. Did you set the the
--api-cors "*"flag (MP_API_CORS="*"env) in Mailpit?@axllent commented on GitHub (Feb 2, 2025):
Sorry, I just realised that the CORS policy only applies to the
/api/*route, and not the/view/*.htmlroute, so that won't currently help.I prefer not to hardcode
target="_blank"in the HTML version as that may impact other existing integrations and/or tests. I believe that if I fix the CORS to also include the/view/*.htmlroute too, then your JavaScript should be allowed to run.@baiomys commented on GitHub (Feb 2, 2025):
Thanks, currently Caddy routes all api calls to/from several mailpits and CORS problem can be solved by complicated redirects,
but it is kind of 'dirty hack' I prefer no to use.
@axllent commented on GitHub (Feb 2, 2025):
Does that mean that it will work for you if I apply (fix) the CORS policy to the html route?
@baiomys commented on GitHub (Feb 2, 2025):
IMHO fixing CORS issue will help to prevent further questions from other users.
You program is getting popular.
=)
@baiomys commented on GitHub (Feb 2, 2025):
Alternatively you can use endpoint already covered by CORS
/api/v1/message/{ID}/part/{PartID}
using part id = html for example to return html
It will also reduce number of routes to handle on reverse-proxy side.
@axllent commented on GitHub (Feb 2, 2025):
I have pushed a change for this to the
axllent/mailpit:edgedocker image (I haven't released it yet). Would you be able to test that to see if it solves your issue please? Thanks.@baiomys commented on GitHub (Feb 2, 2025):
No luck
Uncaught SecurityError: Failed to read a named property 'document' from 'Window': Blocked from accessing a cross-origin frame.It seems that Access-Control-Allow-Origin does not affect IFRAME access as expected
https://stackoverflow.com/questions/23362842/access-control-allow-origin-not-working-for-iframe-within-the-same-domain
Also tried to manually inject Access-Control-Allow-Origin in caddy response. Same result.
Thanks for trying.
@axllent commented on GitHub (Feb 2, 2025):
Hmmm, that is unfortunate. OK, what do you think would solve this issue for you? Is it just the
target="_blank", or is there more to it? You are able to load the iframe from your application, however the links currently just open within the iframe, am I correct?@baiomys commented on GitHub (Feb 2, 2025):
IMHO hardcoding target="_blank" can be helpful not only in my case.
And I am not asking to do something exceptional just for me and right away.
This IFRAME dilemma is obvious and can arise any time soon.
To preserve current API structure, solution can be bound to existing /view or /api/v1/message/{ID}/part/{PartID} endpoint using new context.
@axllent commented on GitHub (Feb 2, 2025):
I've done a bit more reading, and it is a browser-based security restriction to prevent hacking (you won;t be able to work around it via JavaScript). For instance, if I embedded the Gmail login page within an iframe on my malicious site, and then used JavaScript to listen on the input, and submit the data elsewhere as you log in.
If I was to manipulate the HTML on the Mailpit end, I'm not entirely sure what the best way is. The reason is that while there are DOM-parsing libraries there, they always manipulate more than just the anchor tags, they also create
<head>&<body>tags (if they don't already exist), and potentially "fix" broken HTML. This may not be bad in your case, but it would definitely affect user testing.So, I could potentially add a URL variable option, so something like
/view/<id>.html?embed=1or something, which then could do the manipulation, and we don't care if it adds or modifies HTML code. There are some big risks though with embedding as an iframe which you should be aware of, for instance if the HTML email contains inline JavaScript, but that is a different discussion.The other option is that your application reads the HTML message data from the AP, and then injects it into your page. I do something similar already in Mailpit itself, injecting the data into a blank iframe using
srcdocinstead ofsrc. This gives you far more control, however does require several HTML manipulation processes (converting embedded image paths, and I also sanitize the HTML to remove javascript etc). Most of this could be copied from Mailpit's code (although it is in Vue). This is the best way I think, but requires more work on your end. It does however allow you more control to change things like the iframe's height, and opening links in new windows etc.@baiomys commented on GitHub (Feb 2, 2025):
mailpit instance is always self hosted, so you can relatively easy attach regex/sed query via api request parameter and DON'T CARE about result. End user should care.
srcdoc is not an option. It can be implemented only using Caddy templates, which capabilities are too limited.
I cannot afford to process all requests on single core point without distributing among pits.
@axllent commented on GitHub (Feb 2, 2025):
You are embedding the html in an iframe, right? How are you dealing with things like iframe height and styling?
Just so I understand 100% - is adding
target="_blank"the only change you need here to allow your application to preview the HTML message?@baiomys commented on GitHub (Feb 2, 2025):
Well, it's definitely not a secret.
Currently I am using Jinja template.
@axllent commented on GitHub (Feb 2, 2025):
Thanks, but what about my second question of my last message?
@baiomys commented on GitHub (Feb 2, 2025):
All is working in pre-alpha stage.
https://t.me/org_mailbot
Feel free to test if you use telegram.
Currently there is only one testing pit, so CORS is not a problem for now, but there will be more soon.
So if you kindly agree to fix this nasty issue it'll be great.
@axllent commented on GitHub (Feb 2, 2025):
No sorry, I don't have Telegram. Ok, let me think about this a little bit more. There is actually a way an embedded page can call a function (if it exists) in a parent page, which may be the better solution. Sure, you need just the target set, however others may require other functionality too. I've actually done this before in another project, so I'll need to do a bit of digging to see how that worked, and what the limitations (if any) were. At this stage I'm most concerned about security, and also flexibility.
@baiomys commented on GitHub (Feb 2, 2025):
Glad to hear that you are planning major improvements in project.
The most obvious way is to encode
@baiomys commented on GitHub (Feb 2, 2025):
AI generated example using messages
Not sure it's 100% correct, but concept looks usable.
@axllent commented on GitHub (Feb 5, 2025):
OK, so allowing any JavaScript to run between an iframe and its parent is a huge security risk, and is blocked by web browsers. The
postMessage()method can however be safely used to pass variables to the parent page. I have seen some examples which trigger functions, but these are really dangerous, and security in Mailpit is a top priority.So, I've added a feature which is designed for embedding via an iframe. All you need to do is add
?embed=1to the iframe URL and it'll settarget="_blank"to all links. You can read more about this here. It's currently in the edge build, so I'd appreciate it if you could test it for me. Thanks.@baiomys commented on GitHub (Feb 5, 2025):
It works, not sure about embedded JS code location and functions, but links now are definitely target="_blank"
=)
Could you pls alter minor version number (or add some index) on intermediate builds to distinguish one from another.
Thanks for doing such a major improvement !
@baiomys commented on GitHub (Feb 5, 2025):
Looks like message from IFRAME arrives only during source trace in inspector.
In real life only
_console.keymessage arrive.Part of my script section
@axllent commented on GitHub (Feb 5, 2025):
The
postMessage()from the iframe will only fire when the iframe src is fully loaded, including images etc (else we can't calculate the full height). I'm not sure what happens if the iframe itself is hidden as browsers may automatically have "lazy loading" enabled meaning the iframe does not actually load. If you're wanting to adjust the height of the iframe using that functionality, I think it needs to be visible, but maybe set to 100px high or something (initially), and then use the provided JS to reset the height after the frame finishes loading. I'm not too focused on the JS at this point though, the thing you needed was thetarget="_blank"which is the main thing here.I will release a new version of Mailpit
in a few hourstomorrow 👍 Thanks for testing so quickly.@baiomys commented on GitHub (Feb 5, 2025):
You can return data from IFRAME via callable PARENT->IFRAME message.
@axllent commented on GitHub (Feb 6, 2025):
This feature now been released as part of v.1.22.1 👍
@baiomys commented on GitHub (Feb 6, 2025):
Thanks!
Your application is slowly transforming from test tool into advanced middleware.
=)
@axllent commented on GitHub (Feb 6, 2025):
Yeah, but that was never the intention - it is supposed to be a test tool ;-) I am glad you have found a middleware use though.
@baiomys commented on GitHub (Feb 7, 2025):
Hi, data below represents small (400k) email, containing receipt for goods. Nothing special.
Processing time is about 6 (!) seconds on modern Ryzen CPU.
Looks like new code requires some profiling.
=)
@axllent commented on GitHub (Feb 7, 2025):
I do not understand what processing exactly is taking 6 seconds here. Is this for Mailpit to accept the email over SMTP, or return the rendered HTML via the iframe URL, or time taken for your browser to do something with the iframe? How are you profiling this?
@baiomys commented on GitHub (Feb 7, 2025):
6 seconds after making request to /view?embed=1
For some reason code which scans through DOM is terribly slow.
@axllent commented on GitHub (Feb 7, 2025):
That is very strange. Am I able to get a (modified?) copy of this email so I can test please?
@baiomys commented on GitHub (Feb 7, 2025):
It contains some sensitive data, I'll try to remove text and pass html to you asap. Never did it before.
=)
@baiomys commented on GitHub (Feb 7, 2025):
Quick and dirty html extract. There are NO tools to replace text, only to remove tags.... Had to write myself.
https://codebeautify.org/html-pretty-print/y256d9ae3
@axllent commented on GitHub (Feb 7, 2025):
Thank you, I appreciate the effort. I was able to confirm the bug, and with the fix I just pushed (in "edge") I went from 12.9s to 0.149s ;-)
Could you please test the
axllent/mailpit:edgebuild and confirm it solves your issue and makes it fast again?Also, I realise that your HTML was manually edited, but I'm not sure if you realise it is missing the
<head>...</head>and<body>...</body>tags which will break some email clients.@baiomys commented on GitHub (Feb 7, 2025):
It's fine now. No delay. Thanks!
I wrote code in python sandbox (faster than organize separate venv for 30 line project) and there was a problem to "extract" resulting HTML from sandbox page. Some tags "lost in translation".
=)
@axllent commented on GitHub (Feb 7, 2025):
Great. How soon do you need a new release? Can it wait a day or two in case anything else comes up?
@baiomys commented on GitHub (Feb 7, 2025):
Not a problem, my project currently in testing and refactoring stage.