├── CHANGELOG.md ├── FakeSmsEmailTransport.php ├── FakeSmsLoggerTransport.php ├── FakeSmsTransportFactory.php ├── LICENSE ├── README.md └── composer.json /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | 6.2 5 | --- 6 | 7 | * Use `SmsMessage->from` when defined 8 | 9 | 5.4 10 | --- 11 | 12 | * Add the ``FakeSmsLoggerTransport`` 13 | 14 | 5.3 15 | --- 16 | 17 | * Add the bridge 18 | -------------------------------------------------------------------------------- /FakeSmsEmailTransport.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Notifier\Bridge\FakeSms; 13 | 14 | use Symfony\Component\Mailer\Exception\TransportExceptionInterface; 15 | use Symfony\Component\Mailer\MailerInterface; 16 | use Symfony\Component\Mime\Email; 17 | use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException; 18 | use Symfony\Component\Notifier\Message\MessageInterface; 19 | use Symfony\Component\Notifier\Message\SentMessage; 20 | use Symfony\Component\Notifier\Message\SmsMessage; 21 | use Symfony\Component\Notifier\Transport\AbstractTransport; 22 | use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; 23 | use Symfony\Contracts\HttpClient\HttpClientInterface; 24 | 25 | /** 26 | * @author James Hemery 27 | * @author Oskar Stark 28 | */ 29 | final class FakeSmsEmailTransport extends AbstractTransport 30 | { 31 | protected const HOST = 'default'; 32 | 33 | public function __construct( 34 | private MailerInterface $mailer, 35 | private string $to, 36 | private string $from, 37 | ?HttpClientInterface $client = null, 38 | ?EventDispatcherInterface $dispatcher = null, 39 | ) { 40 | parent::__construct($client, $dispatcher); 41 | } 42 | 43 | public function __toString(): string 44 | { 45 | return \sprintf('fakesms+email://%s?to=%s&from=%s', $this->getEndpoint(), $this->to, $this->from); 46 | } 47 | 48 | public function supports(MessageInterface $message): bool 49 | { 50 | return $message instanceof SmsMessage; 51 | } 52 | 53 | /** 54 | * @param MessageInterface|SmsMessage $message 55 | * 56 | * @throws TransportExceptionInterface 57 | */ 58 | protected function doSend(MessageInterface $message): SentMessage 59 | { 60 | if (!$this->supports($message)) { 61 | throw new UnsupportedMessageTypeException(__CLASS__, SmsMessage::class, $message); 62 | } 63 | 64 | $email = (new Email()) 65 | ->from($message->getFrom() ?: $this->from) 66 | ->to($this->to) 67 | ->subject(\sprintf('New SMS on phone number: %s', $message->getPhone())) 68 | ->html($message->getSubject()) 69 | ->text($message->getSubject()); 70 | 71 | if ('default' !== $transportName = $this->getEndpoint()) { 72 | $email->getHeaders()->addTextHeader('X-Transport', $transportName); 73 | } 74 | 75 | $this->mailer->send($email); 76 | 77 | return new SentMessage($message, (string) $this); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /FakeSmsLoggerTransport.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Notifier\Bridge\FakeSms; 13 | 14 | use Psr\Log\LoggerInterface; 15 | use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException; 16 | use Symfony\Component\Notifier\Message\MessageInterface; 17 | use Symfony\Component\Notifier\Message\SentMessage; 18 | use Symfony\Component\Notifier\Message\SmsMessage; 19 | use Symfony\Component\Notifier\Transport\AbstractTransport; 20 | use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; 21 | use Symfony\Contracts\HttpClient\HttpClientInterface; 22 | 23 | /** 24 | * @author Antoine Makdessi 25 | */ 26 | final class FakeSmsLoggerTransport extends AbstractTransport 27 | { 28 | protected const HOST = 'default'; 29 | 30 | public function __construct( 31 | private LoggerInterface $logger, 32 | ?HttpClientInterface $client = null, 33 | ?EventDispatcherInterface $dispatcher = null, 34 | ) { 35 | parent::__construct($client, $dispatcher); 36 | } 37 | 38 | public function __toString(): string 39 | { 40 | return \sprintf('fakesms+logger://%s', $this->getEndpoint()); 41 | } 42 | 43 | public function supports(MessageInterface $message): bool 44 | { 45 | return $message instanceof SmsMessage; 46 | } 47 | 48 | /** 49 | * @param MessageInterface|SmsMessage $message 50 | */ 51 | protected function doSend(MessageInterface $message): SentMessage 52 | { 53 | if (!$this->supports($message)) { 54 | throw new UnsupportedMessageTypeException(__CLASS__, SmsMessage::class, $message); 55 | } 56 | 57 | $this->logger->info(\sprintf('New SMS on phone number: %s', $message->getPhone())); 58 | 59 | return new SentMessage($message, (string) $this); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /FakeSmsTransportFactory.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Notifier\Bridge\FakeSms; 13 | 14 | use Psr\Log\LoggerInterface; 15 | use Symfony\Component\Mailer\MailerInterface; 16 | use Symfony\Component\Notifier\Exception\LogicException; 17 | use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; 18 | use Symfony\Component\Notifier\Transport\AbstractTransportFactory; 19 | use Symfony\Component\Notifier\Transport\Dsn; 20 | use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; 21 | use Symfony\Contracts\HttpClient\HttpClientInterface; 22 | 23 | /** 24 | * @author James Hemery 25 | * @author Oskar Stark 26 | * @author Antoine Makdessi 27 | */ 28 | final class FakeSmsTransportFactory extends AbstractTransportFactory 29 | { 30 | public function __construct( 31 | private ?MailerInterface $mailer = null, 32 | private ?LoggerInterface $logger = null, 33 | ?EventDispatcherInterface $dispatcher = null, 34 | ?HttpClientInterface $client = null, 35 | ) { 36 | parent::__construct($dispatcher, $client); 37 | } 38 | 39 | public function create(Dsn $dsn): FakeSmsEmailTransport|FakeSmsLoggerTransport 40 | { 41 | $scheme = $dsn->getScheme(); 42 | 43 | if ('fakesms+email' === $scheme) { 44 | if (null === $this->mailer) { 45 | $this->throwMissingDependencyException($scheme, MailerInterface::class, 'symfony/mailer'); 46 | } 47 | 48 | $mailerTransport = $dsn->getHost(); 49 | $to = $dsn->getRequiredOption('to'); 50 | $from = $dsn->getRequiredOption('from'); 51 | 52 | return (new FakeSmsEmailTransport($this->mailer, $to, $from, $this->client, $this->dispatcher))->setHost($mailerTransport); 53 | } 54 | 55 | if ('fakesms+logger' === $scheme) { 56 | if (null === $this->logger) { 57 | $this->throwMissingDependencyException($scheme, LoggerInterface::class, 'psr/log'); 58 | } 59 | 60 | return new FakeSmsLoggerTransport($this->logger, $this->client, $this->dispatcher); 61 | } 62 | 63 | throw new UnsupportedSchemeException($dsn, 'fakesms', $this->getSupportedSchemes()); 64 | } 65 | 66 | protected function getSupportedSchemes(): array 67 | { 68 | return ['fakesms+email', 'fakesms+logger']; 69 | } 70 | 71 | private function throwMissingDependencyException(string $scheme, string $missingDependency, string $suggestedPackage): void 72 | { 73 | throw new LogicException(\sprintf('Cannot create a transport for scheme "%s" without providing an implementation of "%s". Try running "composer require "%s"".', $scheme, $missingDependency, $suggestedPackage)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021-present Fabien Potencier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Fake SMS Notifier 2 | ================= 3 | 4 | Provides Fake SMS (as email or log during development) integration for Symfony Notifier. 5 | 6 | #### DSN example for email 7 | 8 | ``` 9 | FAKE_SMS_DSN=fakesms+email://default?to=TO&from=FROM 10 | ``` 11 | 12 | where: 13 | - `TO` is email who receive SMS during development 14 | - `FROM` is email who send SMS during development 15 | 16 | To use a custom mailer transport: 17 | 18 | ``` 19 | FAKE_SMS_DSN=fakesms+email://mailchimp?to=TO&from=FROM 20 | ``` 21 | 22 | #### DSN example for logger 23 | 24 | ``` 25 | FAKE_SMS_DSN=fakesms+logger://default 26 | ``` 27 | 28 | Resources 29 | --------- 30 | 31 | * [Contributing](https://symfony.com/doc/current/contributing/index.html) 32 | * [Report issues](https://github.com/symfony/symfony/issues) and 33 | [send Pull Requests](https://github.com/symfony/symfony/pulls) 34 | in the [main Symfony repository](https://github.com/symfony/symfony) 35 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony/fake-sms-notifier", 3 | "type": "symfony-notifier-bridge", 4 | "description": "Fake SMS (as email or log during development) Notifier Bridge.", 5 | "keywords": ["sms", "development", "email", "notifier", "symfony"], 6 | "homepage": "https://symfony.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "James Hemery", 11 | "homepage": "https://github.com/JamesHemery" 12 | }, 13 | { 14 | "name": "Antoine Makdessi", 15 | "email": "amakdessi@me.com", 16 | "homepage": "http://antoine.makdessi.free.fr" 17 | }, 18 | { 19 | "name": "Symfony Community", 20 | "homepage": "https://symfony.com/contributors" 21 | } 22 | ], 23 | "require": { 24 | "php": ">=8.2", 25 | "symfony/http-client": "^6.4|^7.0", 26 | "symfony/notifier": "^7.2" 27 | }, 28 | "require-dev": { 29 | "psr/log": "^1|^2|^3", 30 | "symfony/mailer": "^6.4|^7.0" 31 | }, 32 | "autoload": { 33 | "psr-4": { "Symfony\\Component\\Notifier\\Bridge\\FakeSms\\": "" }, 34 | "exclude-from-classmap": [ 35 | "/Tests/" 36 | ] 37 | }, 38 | "minimum-stability": "dev" 39 | } 40 | --------------------------------------------------------------------------------