diff --git a/CHANGELOG.md b/CHANGELOG.md
index 626e7a03..cceff90f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
+## [Unreleased]
+### Added
+* *Nothing*
+
+### Changed
+* *Nothing*
+
+### Deprecated
+* *Nothing*
+
+### Removed
+* *Nothing*
+
+### Fixed
+* [#1742](https://github.com/shlinkio/shlink/issues/1742) Fix URLs using schemas which do not contain `//`, like `mailto:`, to no longer be considered valid.
+
+
## [3.5.3] - 2023-03-31
### Added
* *Nothing*
diff --git a/config/constants.php b/config/constants.php
index 77f81fdd..35d4c56e 100644
--- a/config/constants.php
+++ b/config/constants.php
@@ -13,7 +13,7 @@ const DEFAULT_REDIRECT_STATUS_CODE = RedirectStatus::STATUS_302; // Deprecated.
const DEFAULT_REDIRECT_CACHE_LIFETIME = 30;
const LOCAL_LOCK_FACTORY = 'Shlinkio\Shlink\LocalLockFactory';
const TITLE_TAG_VALUE = '/
]*>(.*?)<\/title>/i'; // Matches the value inside a html title tag
-const LOOSE_URI_MATCHER = '/(.+)\:\/\/(.+)/i'; // Matches anything starting with a schema.
+const LOOSE_URI_MATCHER = '/(.+)\:(.+)/i'; // Matches anything starting with a schema.
const DEFAULT_QR_CODE_SIZE = 300;
const DEFAULT_QR_CODE_MARGIN = 0;
const DEFAULT_QR_CODE_FORMAT = 'png';
diff --git a/module/Core/test/ShortUrl/Model/ShortUrlCreationTest.php b/module/Core/test/ShortUrl/Model/ShortUrlCreationTest.php
index bb82ee8e..17a8f581 100644
--- a/module/Core/test/ShortUrl/Model/ShortUrlCreationTest.php
+++ b/module/Core/test/ShortUrl/Model/ShortUrlCreationTest.php
@@ -165,6 +165,20 @@ class ShortUrlCreationTest extends TestCase
yield ['гугл', 'гугл'];
}
+ #[Test, DataProvider('provideValidLongUrls')]
+ public function supportsDifferentTypesOfSchemas(string $longUrl): void
+ {
+ $creation = ShortUrlCreation::fromRawData(['longUrl' => $longUrl]);
+ self::assertEquals($longUrl, $creation->longUrl);
+ }
+
+ public static function provideValidLongUrls(): iterable
+ {
+ yield 'mailto' => ['mailto:foo@example.com'];
+ yield 'file' => ['file:///foo/bar'];
+ yield 'https' => ['https://example.com'];
+ }
+
#[Test, DataProvider('provideTitles')]
public function titleIsCroppedIfTooLong(?string $title, ?string $expectedTitle): void
{