using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace MailSharp.MailClient.Controllers; // Serves only the page shells - all data (folders, messages, translations, sending mail) is // fetched client-side from Controllers/Api via mail.js / compose.js. Must stay reachable while // logged out (mail.js itself redirects to /Account/Login on a 401 from the API), and since // MapControllers() and MapControllerRoute() share the same endpoint data source, // RequireAuthorization() on the API routes would otherwise leak onto this controller too. [AllowAnonymous] public class MailController : Controller { [HttpGet] public IActionResult Index() => View(); [HttpGet] public IActionResult Compose() => View(); // Interstitial every link inside a rendered message HTML body gets rewritten to point at (see // ImageSanitizer.ApplyLinkPolicy) - lets the user confirm before a sender-controlled URL // actually runs, and opens in a real top-level tab instead of the sandboxed message iframe so // no destination site can refuse to be framed. 404s rather than open-redirecting on anything // that isn't a well-formed http(s) URL, since url is attacker-influenced (it's copied straight // out of an email). [HttpGet] public IActionResult ExternalLink(string url) { if (!Uri.TryCreate(url, UriKind.Absolute, out var parsed) || (parsed.Scheme != Uri.UriSchemeHttp && parsed.Scheme != Uri.UriSchemeHttps)) { return NotFound(); } ViewData["ExternalUrl"] = parsed.AbsoluteUri; ViewData["ExternalHost"] = parsed.Host; return View(); } }