fixed site

This commit is contained in:
2026-03-29 17:20:43 +02:00
parent c9e3d971c4
commit d433869348
153 changed files with 6766 additions and 1653 deletions
+619
View File
@@ -0,0 +1,619 @@
<!doctype html>
<html
lang="de-DE"
dir="ltr"
class="h-full">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="language" content="de-DE">
<script>
(function () {
const storedTheme = localStorage.getItem("theme");
const systemPrefersLight = window.matchMedia("(prefers-color-scheme: light)").matches;
const theme = storedTheme || (systemPrefersLight ? "light" : "dark");
document.documentElement.setAttribute("data-theme", theme);
})();
</script>
<title>Blocking Invalid Recipients Before They Reach Your Exchange Server | Demians Blog</title>
<meta
name="description"
content="
Recently, I had to deal with a serious problem: backscatter.
One of our mail gateways ended up listed on the backscatter.org blacklist for sending bounce …
">
<link rel="canonical" href="https://pyte.dev/posts/blocking-invalid-rcpt-postfix/">
<meta name="robots" content="index, follow">
<meta property="og:type" content="article">
<meta property="og:title" content="Blocking Invalid Recipients Before They Reach Your Exchange Server | Demians Blog">
<meta property="og:description" content="Recently, I had to deal with a serious problem: backscatter.
One of our mail gateways ended up listed on the backscatter.org blacklist for sending bounce …">
<meta property="og:url" content="https://pyte.dev/posts/blocking-invalid-rcpt-postfix/">
<meta property="og:site_name" content="Demians Blog"><meta property="og:image" content="https://pyte.dev/assets/patrick.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630"><meta property="article:published_time" content="2025-08-01T10:03:15&#43;02:00">
<meta
property="article:modified_time"
content="2025-08-01T10:03:15&#43;02:00">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Blocking Invalid Recipients Before They Reach Your Exchange Server | Demians Blog">
<meta name="twitter:description" content="Recently, I had to deal with a serious problem: backscatter.
One of our mail gateways ended up listed on the backscatter.org blacklist for sending bounce …"><meta name="twitter:image" content="https://pyte.dev/assets/patrick.png">
<script type="application/ld+json">
"{\"@context\":\"https://schema.org\",\"@type\":\"BlogPosting\",\"author\":{\"@type\":\"Person\",\"email\":\"demian (at) pyte (dot) dev\",\"name\":\"Demians Blog\"},\"dateModified\":\"2025-08-01T10:03:15+02:00\",\"datePublished\":\"2025-08-01T10:03:15+02:00\",\"description\":\"Recently, I had to deal with a serious problem: backscatter.\\nOne of our mail gateways ended up listed on the backscatter.org blacklist for sending bounce …\",\"headline\":\"Blocking Invalid Recipients Before They Reach Your Exchange Server\",\"image\":\"https://pyte.dev/assets/patrick.png\",\"mainEntityOfPage\":{\"@id\":\"https://pyte.dev/posts/blocking-invalid-rcpt-postfix/\",\"@type\":\"WebPage\"},\"publisher\":{\"@type\":\"Organization\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://pyte.dev/assets/patrick.png\"},\"name\":\"Demians Blog\"}}"</script>
<script type="application/ld+json">"{\"@context\":\"https://schema.org\",\"@type\":\"BreadcrumbList\",\"itemListElement\":[{\"@type\":\"ListItem\",\"item\":\"https://pyte.dev/\",\"name\":\"Demians Blog\",\"position\":1},{\"@type\":\"ListItem\",\"item\":\"https://pyte.dev/posts/\",\"name\":\"Posts\",\"position\":2},{\"@type\":\"ListItem\",\"item\":\"https://pyte.dev/posts/blocking-invalid-rcpt-postfix/\",\"name\":\"Blocking Invalid Recipients Before They Reach Your Exchange Server\",\"position\":3}]}"</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&family=Outfit:wght@400;500;600;700;800;900&family=Space+Grotesk:wght@400;500;600;700&display=swap"
rel="stylesheet">
<link
rel="stylesheet"
href="/css/theme.min.86a32b729f656fc6c119ed69193950db815a3ad9fdc967b32c76d602f11449a4.css"
integrity="sha256-hqMrcp9lb8bBGe1pGTlQ24FaOtn9yWezLHbWAvEUSaQ=">
<link
rel="stylesheet"
href="/css/syntax-dark.min.3e403a03e3af837b3829e9b6f01fc7792bda7cb7f5056f5e9786109545c6b2e1.css"
integrity="sha256-PkA6A&#43;Ovg3s4Kem28B/HeSvafLf1BW9el4YQlUXGsuE="
id="syntax-dark-theme"
class="syntax-theme"><link
rel="stylesheet"
href="/css/syntax-light.min.d0d33b879698595e6b2c0f75f0cea95a8517fb0150570cd0ee4dc42e25c8d147.css"
integrity="sha256-0NM7h5aYWV5rLA918M6pWoUX&#43;wFQVwzQ7k3ELiXI0Uc="
id="syntax-light-theme"
class="syntax-theme"
disabled><script>
(function () {
const storedTheme = localStorage.getItem("theme");
const systemPrefersLight = window.matchMedia("(prefers-color-scheme: light)").matches;
const theme = storedTheme || (systemPrefersLight ? "light" : "dark");
const syntaxDark = document.getElementById("syntax-dark-theme");
const syntaxLight = document.getElementById("syntax-light-theme");
if (theme === "light") {
if (syntaxDark) syntaxDark.disabled = true;
if (syntaxLight) syntaxLight.disabled = false;
} else {
if (syntaxDark) syntaxDark.disabled = false;
if (syntaxLight) syntaxLight.disabled = true;
}
const observer = new MutationObserver(() => {
const currentTheme = document.documentElement.getAttribute("data-theme");
if (currentTheme === "light") {
if (syntaxDark) syntaxDark.disabled = true;
if (syntaxLight) syntaxLight.disabled = false;
} else {
if (syntaxDark) syntaxDark.disabled = false;
if (syntaxLight) syntaxLight.disabled = true;
}
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["data-theme"],
});
})();
</script>
<link
rel="stylesheet"
href="/css/bundle.min.783a79746a859af9be598cbc33fba2a1087434b23768524277b07ef28336f113.css"
integrity="sha256-eDp5dGqFmvm&#43;WYy8M/uioQh0NLI3aFJCd7B&#43;8oM28RM=">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/png" href="/favicon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/logo-transparent/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/logo-transparent/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/logo-transparent/apple-touch-icon.png">
<link
rel="icon"
type="image/png"
sizes="192x192"
href="/favicon/logo-transparent/android-chrome-192x192.png">
<link
rel="icon"
type="image/png"
sizes="512x512"
href="/favicon/logo-transparent/android-chrome-512x512.png">
<link rel="manifest" href="/favicon/logo-transparent/site.webmanifest">
</head>
<body class="flex flex-col min-h-screen">
<a href="#main-content" class="skip-to-main" aria-label="Skip to main content"
>Skip to main content</a
>
<header class="sticky-header">
<div class="header-container">
<nav class="header-nav" role="navigation" aria-label="Main navigation">
<div class="header-content">
<div class="header-logo">
<a href="/" class="logo-link" aria-label="Home - Demians Blog">
Demians Blog
</a>
</div>
<div class="header-menu">
<ul class="menu-list">
<li class="menu-item">
<a
href="/"
class="menu-link ">
Home
</a>
</li>
<li class="menu-item">
<a
href="/posts/"
class="menu-link ">
Blog
</a>
</li>
</ul>
<button id="search-toggle" class="search-toggle" aria-label="Search" type="button">
<svg class="search-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
</button>
<button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme" type="button">
<svg class="icon-sun" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path>
</svg>
<svg class="icon-moon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path>
</svg>
</button>
</div>
</div>
</nav>
</div>
</header>
<main id="main-content" class="flex-1" role="main">
<div class="single-post-wrapper">
<article class="single-post">
<header class="post-header">
<h1 class="post-title-main">Blocking Invalid Recipients Before They Reach Your Exchange Server</h1>
<div class="post-meta">
<div class="post-meta-info">
<time datetime="2025-08-01T10:03:15&#43;02:00" class="post-date">
<svg class="meta-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
August 1, 2025
</time>
<span class="meta-separator"></span>
<span class="post-word-count">
<svg class="meta-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
762 words
</span>
<span class="meta-separator"></span>
<span class="post-reading-time">
<svg class="meta-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
4 min
</span>
</div>
</div>
</header>
<div class="post-content-main">
<p>Recently, I had to deal with a serious problem: <strong>backscatter</strong>.<br>
One of our mail gateways ended up listed on the <strong>backscatter.org</strong> blacklist for sending bounce messages to forged senders.</p>
<p>After checking the logs, I quickly realized that our system wasn&rsquo;t actually protected against backscatter attacks, so I had to do something about it.</p>
<h2 id="what-even-is-backscatter">What Even Is Backscatter?</h2>
<p>Backscatter is unwanted email that your mail server sends <strong>after</strong> receiving a message, usually in the form of a <strong>non-delivery report (NDR)</strong> or <strong>bounce</strong> to a <strong>forged sender address</strong>.</p>
<p>It happens when:</p>
<ul>
<li>A spammer sends email with a <strong>fake &ldquo;From&rdquo; address</strong> (often an innocent third party).</li>
<li>Your mail server <strong>accepts</strong> the message first, but later discovers its undeliverable.</li>
<li>Your server sends a <strong>bounce</strong> to the forged address, hitting an innocent person instead of the spammer.</li>
</ul>
<p>This makes your server appear to be sending spam, even though you&rsquo;re just bouncing bad mail.</p>
<h2 id="the-problem-in-our-setup">The Problem in Our Setup</h2>
<p>Our mail gateway mostly relays mail to multiple internal Exchange Server clusters.<br>
We have a list of valid domains configured, so Postfix will only accept mail for those domains.</p>
<p><strong>The problem?</strong><br>
Postfix didn&rsquo;t know which individual recipients were valid on the downstream Exchange servers.<br>
That meant it would happily accept messages for <strong>nonexistent users</strong>, only to later bounce them, classic backscatter behavior.</p>
<h2 id="the-goal">The Goal</h2>
<p>We needed to reject mail <strong>during the SMTP session</strong>, ideally right after the <code>RCPT TO</code> command, if the recipient didn&rsquo;t exist on the Exchange servers.</p>
<p>That way, the sending server would get the rejection immediately, and we would never have to generate a bounce message.</p>
<h2 id="possible-solutions-i-considered">Possible Solutions I Considered</h2>
<h3 id="1-relay_"><strong>1. relay_recipient_maps</strong></h3>
<p>This would require maintaining a <strong>full list of valid recipients</strong> in a Postfix lookup table.<br>
It works well, but means writing and maintaining a script to <strong>sync the list from Active Directory</strong> on a regular basis.</p>
<p>For us, this was too much custom scripting, too fragile, and too messy to maintain.</p>
<h3 id="2-virtual_"><strong>2. virtual_mailbox_maps with LDAP</strong></h3>
<p>Another approach would be using <strong>LDAP lookups</strong> directly against Active Directory to verify recipients in real-time.</p>
<p>This can work in some setups, but:</p>
<ul>
<li>It adds complexity and dependencies.</li>
<li>It can introduce security concerns.</li>
<li>It didnt fit well with our environment.</li>
</ul>
<p>So I ruled it out.</p>
<h2 id="the-solution-reject_unverified_recipient">The Solution: <code>reject_unverified_recipient</code></h2>
<p>While reading through the <strong>Postfix Address Verification Howto</strong>, I came across the <code>reject_unverified_recipient</code> option - bling! - exactly what I needed.</p>
<h3 id="how-it-works"><strong>How It Works</strong></h3>
<p>When an incoming SMTP session reaches the <code>RCPT TO</code> stage:</p>
<ol>
<li>Postfix checks if <code>reject_unverified_recipient</code> is enabled for the recipient domain.</li>
<li>If yes, it temporarily <strong>probes the downstream mail system</strong> to see if the recipient address exists.</li>
<li>If the downstream system says:
<ul>
<li><strong>User exists</strong> → Postfix continues processing.</li>
<li><strong>User does not exist</strong> → Postfix <strong>rejects immediately</strong> with:
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">550 5.1.1 &lt;user@example.de&gt;: Recipient address rejected: User unknown
</span></span></code></pre></div></li>
</ul>
</li>
</ol>
<p>Because the rejection happens <strong>during SMTP</strong>, no bounce is generated, and backscatter is avoided entirely.</p>
<h2 id="implementation-in-ispconfig">Implementation in ISPConfig</h2>
<p>In our case, the mail gateways run <strong>Postfix</strong> with <strong>ISPConfig</strong> as the management interface.<br>
I implemented a new configuration option in ISPConfig for <strong>per-domain control</strong> of <code>reject_unverified_recipient</code>, along with a <strong>validation server</strong> to specify for the downstream validation server.</p>
<h3 id="specifying-a-validation-server-for-recipient-verification">Specifying a Validation Server for Recipient Verification</h3>
<p>One important detail is that Exchange servers cannot validate recipients over the default SMTP transport on port <code>25</code>. To enable recipient validation, you need to activate it on the Exchange server and use the Hub Transport service, which by default runs on port <code>2525</code>.</p>
<p>Make sure to restrict access to this port, as it requires anonymous login specifically for recipient validation, you don&rsquo;t want that exposed broadly.</p>
<blockquote class="blockquote-regular">
<p><strong>Note:</strong> This setup does not affect your regular mail flow. Only the SMTP probes used for verifying recipients are sent to this validation server.<br>
Postfix enables this behavior with the <code>address_verify_transport_maps</code> option.</p>
</blockquote>
<p>To optimize performance and reduce unnecessary verification probes for addresses that have already been checked, I configured a local cache on the mail gateway using the <code>address_verify_map</code> option. This way, repeated probes for the same recipient are avoided.</p>
<p>Now, for domains that need recipient verification, we can enable it in the panel and point Postfix to the appropriate <strong>validation transport</strong>.</p>
<h2 id="the-result">The Result</h2>
<p>After enabling <code>reject_unverified_recipient</code> and pointing it at the Exchange clusters, the backscatter stopped completely.<br>
We were no longer accepting messages for invalid recipients.</p>
<h2 id="conclusion">Conclusion</h2>
<p>If your Postfix server is acting as a relay for Exchange (or any downstream mail system) and you&rsquo;re struggling with <strong>backscatter spam</strong>, enabling <code>reject_unverified_recipient</code> can be a clean and effective fix.</p>
<p>It avoids maintaining large static recipient maps, works dynamically, and ensures that invalid mail is rejected <strong>before</strong> it ever gets into your system.</p>
</div>
<nav class="post-navigation" aria-label="Post navigation">
<a
href="/posts/dovecot-index-cache-issues/"
class="nav-link nav-prev"
aria-label="Previous post: Dovecot Index Cache Issues">
<span class="nav-label">Previous</span>
<span class="nav-title">Dovecot Index Cache Issues</span>
</a>
<a
href="/posts/google-groups-spam/"
class="nav-link nav-next"
aria-label="Next post: Google Groups Spam">
<span class="nav-label">Next</span>
<span class="nav-title">Google Groups Spam</span>
</a>
</nav>
</article>
<aside class="post-toc" id="post-toc" aria-label="Table of contents">
<button
class="toc-toggle"
id="toc-toggle"
aria-expanded="true"
aria-controls="toc-content"
aria-label="Toggle table of contents">
<svg
class="toc-burger-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true">
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
<span class="toc-toggle-text">Table of Contents</span>
<svg
class="toc-chevron-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
<div class="toc-content" id="toc-content">
<nav class="toc-nav" aria-label="Table of contents">
<nav id="TableOfContents">
<ul>
<li><a href="#what-even-is-backscatter">What Even Is Backscatter?</a></li>
<li><a href="#the-problem-in-our-setup">The Problem in Our Setup</a></li>
<li><a href="#the-goal">The Goal</a></li>
<li><a href="#possible-solutions-i-considered">Possible Solutions I Considered</a>
<ul>
<li><a href="#1-relay_"><strong>1. relay_recipient_maps</strong></a></li>
<li><a href="#2-virtual_"><strong>2. virtual_mailbox_maps with LDAP</strong></a></li>
</ul>
</li>
<li><a href="#the-solution-reject_unverified_recipient">The Solution: <code>reject_unverified_recipient</code></a>
<ul>
<li><a href="#how-it-works"><strong>How It Works</strong></a></li>
</ul>
</li>
<li><a href="#implementation-in-ispconfig">Implementation in ISPConfig</a>
<ul>
<li><a href="#specifying-a-validation-server-for-recipient-verification">Specifying a Validation Server for Recipient Verification</a></li>
</ul>
</li>
<li><a href="#the-result">The Result</a></li>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
</nav>
</nav>
</div>
</aside>
</div>
</main>
<footer>
<footer class="site-footer">
<div class="footer-content">
<p class="footer-text">
&copy;
2026
Demians Blog.
Built with Hugo and Mana ❤️
</p>
<div class="footer-social">
<div class="social-links">
<a
href="https://github.com/pyte1"
target="_blank"
rel="noopener noreferrer"
class="social-link"
aria-label="GitHub">
<svg fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path
fill-rule="evenodd"
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
clip-rule="evenodd"></path>
</svg>
</a>
<a href="mailto:demian%20%28at%29%20pyte%20%28dot%29%20dev" class="social-link" aria-label="Email">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
</svg>
</a>
</div>
</div>
</div>
</footer>
</footer>
<div id="search-modal" class="search-modal" aria-hidden="true" role="dialog" aria-label="Search">
<div class="search-modal-backdrop" id="search-modal-backdrop"></div>
<div class="search-modal-container">
<div class="search-input-wrapper">
<svg class="search-input-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
<input
type="search"
id="search-input"
class="search-input"
placeholder="Search..."
autocomplete="off"
aria-label="Search input">
<button class="search-input-clear" id="search-input-clear" aria-label="Clear search">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
</button>
<button class="search-modal-close" id="search-modal-close" aria-label="Close search">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<div id="search-results" class="search-results"></div>
</div>
</div>
<button id="scroll-to-top" class="scroll-to-top" aria-label="Scroll to top" type="button">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 10l7-7m0 0l7 7m-7-7v18"></path>
</svg>
</button>
<script src="/js/main.min.e60ab79dca7b920b4dc5cf3163ad5ce8794839b60f27778db65782f087be3e27.js" defer></script>
</body>
</html>