├── Config └── CatcherConfig.php ├── Logger ├── Handler │ ├── Debug.php │ ├── Error.php │ ├── HandlerAbstract.php │ ├── HandlerFactory.php │ └── Info.php └── MailCatcherLogger.php ├── Mail └── Message.php ├── Plugin └── HandleMailTransportPlugin.php ├── README.md ├── Repository └── MailCatcherRepository.php ├── Test └── Integration │ ├── MailTransportTest.php │ └── TransportBuilderFake.php ├── Transport └── MailCatcherTransportProxy.php ├── composer.json ├── docs └── img │ └── mailcatcher_admin.png ├── etc ├── acl.xml ├── adminhtml │ └── system.xml ├── config.xml ├── di.xml ├── email_templates.xml └── module.xml ├── registration.php └── view └── adminhtml └── email └── test.html /Config/CatcherConfig.php: -------------------------------------------------------------------------------- 1 | scopeConfig = $scopeConfig; 28 | } 29 | 30 | public function isCatcherEnabled() : bool 31 | { 32 | return $this->scopeConfig->getValue(self::XML_PATH_ENABLED); 33 | } 34 | 35 | public function whiteList() : array 36 | { 37 | $whiteListConfig = $this->scopeConfig->getValue(self::XML_PATH_WHITELIST); 38 | if ($whiteListConfig) { 39 | return array_map('trim', explode(',', $whiteListConfig)); 40 | } 41 | return []; 42 | } 43 | 44 | /** 45 | * @return mixed 46 | */ 47 | public function redirectRecipient() 48 | { 49 | return $this->scopeConfig->getValue(self::XML_PATH_REDIRECT_RECIPIENT); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /Logger/Handler/Debug.php: -------------------------------------------------------------------------------- 1 | '\\Staempfli\\MailCatcher\\Logger\\Handler\\Error', 31 | 'info' => '\\Staempfli\\MailCatcher\\Logger\\Handler\\Info', 32 | 'debug' => '\\Staempfli\\MailCatcher\\Logger\\Handler\\Debug', 33 | ]; 34 | 35 | /** 36 | * Factory constructor 37 | * 38 | * @param ObjectManagerInterface $objectManager 39 | */ 40 | public function __construct(ObjectManagerInterface $objectManager) 41 | { 42 | $this->objectManager = $objectManager; 43 | } 44 | 45 | /** 46 | * Create corresponding class instance 47 | * 48 | * @param $type 49 | * @param array $data 50 | * @return ObjectType 51 | */ 52 | public function create($type, array $data = array()) 53 | { 54 | if (empty($this->instanceTypeNames[$type])) { 55 | throw new InvalidArgumentException('"' . $type . ': isn\'t allowed'); 56 | } 57 | 58 | $resultInstance = $this->objectManager->create($this->instanceTypeNames[$type], $data); 59 | if (!$resultInstance instanceof ObjectType) { 60 | throw new InvalidArgumentException(get_class($resultInstance) . ' isn\'t instance of \Staempfli\MailCatcher\Logger\Handler\HandlerAbstract'); 61 | } 62 | 63 | return $resultInstance; 64 | } 65 | } -------------------------------------------------------------------------------- /Logger/Handler/Info.php: -------------------------------------------------------------------------------- 1 | defaultHandlerTypes as $handlerType) { 35 | if (!array_key_exists($handlerType, $handlers)) { 36 | $handlers[$handlerType] = $handlerFactory->create($handlerType); 37 | } 38 | } 39 | parent::__construct($name, $handlers, $processors); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /Mail/Message.php: -------------------------------------------------------------------------------- 1 | catcherConfig = $catcherConfig; 32 | $this->mailCatcherRepository = $mailCatcherRepository; 33 | parent::__construct($charset); 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function AddTo($address, $name = '') 40 | { 41 | $redirectAddress = $this->getRedirectRecipient($address); 42 | if ($redirectAddress) { 43 | $address = $redirectAddress; 44 | } 45 | parent::addTo($address, $name); 46 | } 47 | 48 | /** 49 | * {@inheritdoc} 50 | */ 51 | public function addCc($address, $name = '') 52 | { 53 | $redirectAddress = $this->getRedirectRecipient($address); 54 | if ($redirectAddress) { 55 | $address = $redirectAddress; 56 | } 57 | return parent::addCc($address, $name); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function addBcc($address) 64 | { 65 | $redirectAddress = $this->getRedirectRecipient($address); 66 | if ($redirectAddress) { 67 | $address = $redirectAddress; 68 | } 69 | return parent::addBcc($address); 70 | } 71 | 72 | /** 73 | * @param $address 74 | * @return bool|string|array 75 | */ 76 | private function getRedirectRecipient($address) 77 | { 78 | if ($this->catcherConfig->isCatcherEnabled()) { 79 | $redirectRecipient = $this->catcherConfig->redirectRecipient(); 80 | if ($redirectRecipient) { 81 | return $this->getAddressWithRedirectRecipient($address, $redirectRecipient); 82 | } 83 | } 84 | return false; 85 | } 86 | 87 | /** 88 | * @param $address 89 | * @param $redirectRecipient 90 | * @return array|string 91 | */ 92 | private function getAddressWithRedirectRecipient($address, $redirectRecipient) 93 | { 94 | if (is_array($address)) { 95 | foreach ($address as &$email) { 96 | if (!$this->mailCatcherRepository->isRecipientWhiteListed($email)) { 97 | $email = $redirectRecipient; 98 | } 99 | } 100 | } 101 | if (is_string($address)) { 102 | if (!$this->mailCatcherRepository->isRecipientWhiteListed($address)) { 103 | $address = $redirectRecipient; 104 | } 105 | } 106 | return $address; 107 | } 108 | 109 | } -------------------------------------------------------------------------------- /Plugin/HandleMailTransportPlugin.php: -------------------------------------------------------------------------------- 1 | catcherConfig = $catcherConfig; 31 | $this->mailCatcherTransportProxyFactory = $mailCatcherTransportProxyFactory; 32 | } 33 | 34 | /** 35 | * @param TransportInterfaceFactory $subject 36 | * @param callable $proceed 37 | * @param array $data 38 | * @return mixed 39 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 40 | */ 41 | public function aroundCreate(TransportInterfaceFactory $subject, callable $proceed, array $data = []) 42 | { 43 | if ($this->catcherConfig->isCatcherEnabled()) { 44 | $data['originalTransport'] = $proceed($data); 45 | return $this->mailCatcherTransportProxyFactory->create($data); 46 | } 47 | return $proceed($data); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Magento 2 Mail Catcher 2 | 3 | [![Project Status: Abandoned – Initial development has started, but there has not yet been a stable, usable release; the project has been abandoned and the author(s) do not intend on continuing development.](http://www.repostatus.org/badges/latest/abandoned.svg)](http://www.repostatus.org/#abandoned) 4 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/3711ac6ffa0b44848de375b54ae21c0d)](https://www.codacy.com/app/Staempfli/magento2-module-mailcatcher?utm_source=github.com&utm_medium=referral&utm_content=staempfli/magento2-module-mailcatcher&utm_campaign=Badge_Grade) 5 | [![Code Climate](https://codeclimate.com/github/staempfli/magento2-module-mailcatcher/badges/gpa.svg)](https://codeclimate.com/github/staempfli/magento2-module-mailcatcher) 6 | [![Issue Count](https://codeclimate.com/github/staempfli/magento2-module-mailcatcher/badges/issue_count.svg)](https://codeclimate.com/github/staempfli/magento2-module-mailcatcher) 7 | 8 | Magento 2 module to catch, log and redirect emails on local and stage enviroments. 9 | 10 | Features: 11 | 12 | * Catch and log all emails 13 | * Whitelist domains or emails that you do not want to catch (Merchant domain, developer emails) 14 | * Redirect catched emails to a [trash-mail](https://www.trash-mail.com/inbox/) instead of logging them 15 | 16 | ## Introduction 17 | 18 | Although the recommended way to catch emails is using a mailCatcher like [MailHog](https://github.com/mailhog/MailHog), this is not always easy to setup in all environments and configurations: 19 | 20 | Facts: 21 | 22 | * Not all your developers have same local systems and configurations 23 | * Stage servers might use different mail transfer agents (sendmail, postfix) 24 | * Projects might use the merchant STMP server for sending emails 25 | * Merchants want to test how real emails are sent and not use a catching Web UI 26 | 27 | If you have these problems, that's when this module comes in handy. This module catches emails before they reach the transfer agent. No extra tools needed for your projects, simply install and enable it on Magento Admin. 28 | 29 | 30 | ## Installation 31 | 32 | ``` 33 | $ composer require "staempfli/magento2-module-mailcatcher":"~1.0" 34 | ``` 35 | 36 | ## Usage 37 | 38 | `Magento Admin > Stores > Configuration > Staempfli > Mail Catcher` 39 | 40 | ![Mail Catcher Admin Configuration](docs/img/mailcatcher_admin.png) 41 | 42 | ## Disclaimer 43 | 44 | This module uses a plugin on `Magento\Framework\Mail\TransportInterfaceFactory::create()`, watch out that your code or other modules installed do not overrite that method. 45 | 46 | See: [etc/di.xml](etc/di.xml) 47 | 48 | ## Tests 49 | 50 | In order to prove that the mail catcher always work, we recommend you to run included integration tests on your CI environment. Add this into your `dev/tests/integration/framework/phpunit.xml`: 51 | 52 | ``` 53 | &magentoDir;/vendor/staempfli/magento2-module-mailcatcher/Test/Integration 54 | ``` 55 | 56 | ## Prerequisites 57 | 58 | - PHP >= 7.0.* 59 | - Magento >= 2.1.* 60 | 61 | ## Developers 62 | 63 | Juan Alonso, and all other [contributors](https://github.com/staempfli/magento2-module-mailcatcher/contributors) 64 | 65 | ## License 66 | 67 | [Open Software License ("OSL") v. 3.0](https://opensource.org/licenses/OSL-3.0) 68 | 69 | ## Copyright 70 | 71 | (c) 2017, Stämpfli AG 72 | -------------------------------------------------------------------------------- /Repository/MailCatcherRepository.php: -------------------------------------------------------------------------------- 1 | catcherConfig = $catcherConfig; 24 | } 25 | 26 | public function isRecipientWhiteListed(string $recipient) : bool 27 | { 28 | if (in_array($recipient, $this->catcherConfig->whiteList())) { 29 | return true; 30 | } 31 | if ($this->isRecipientDomainInWhitelist($recipient)) { 32 | return true; 33 | } 34 | return false; 35 | } 36 | 37 | private function isRecipientDomainInWhitelist(string $recipient) : bool 38 | { 39 | $emailParts = explode('@', $recipient); 40 | $recipientDomain = array_pop($emailParts); 41 | if (in_array($recipientDomain, $this->catcherConfig->whiteList())) { 42 | return true; 43 | } 44 | return false; 45 | } 46 | 47 | public function isRedirectRecipient(string $recipient) : bool 48 | { 49 | $redirectRecipient = $this->catcherConfig->redirectRecipient(); 50 | return $recipient === $redirectRecipient; 51 | } 52 | } -------------------------------------------------------------------------------- /Test/Integration/MailTransportTest.php: -------------------------------------------------------------------------------- 1 | transportBuilder = $objectManager->create(TransportBuilderFake::class); 58 | } 59 | 60 | public static function loadEnableCatcherConfiguration() 61 | { 62 | $config = ObjectManager::getInstance()->get(Config::class); 63 | $config->saveConfig(CatcherConfig::XML_PATH_ENABLED, 1, 'default', 0); 64 | $config->saveConfig(CatcherConfig::XML_PATH_WHITELIST, '', 'default', 0); 65 | $config->saveConfig(CatcherConfig::XML_PATH_REDIRECT_RECIPIENT, '', 'default', 0); 66 | } 67 | 68 | public static function loadDisableCatcherConfiguration() 69 | { 70 | $config = ObjectManager::getInstance()->get(Config::class); 71 | $config->saveConfig(CatcherConfig::XML_PATH_ENABLED, 0, 'default', 0); 72 | } 73 | 74 | public static function loadEnableWithWhitelistCatcherConfiguration() 75 | { 76 | $config = ObjectManager::getInstance()->get(Config::class); 77 | $config->saveConfig(CatcherConfig::XML_PATH_ENABLED, 1, 'default', 0); 78 | $whiteListConfig = implode(',', array_merge(self::$whiteListEmails, self::$whiteListDomains)); 79 | $config->saveConfig(CatcherConfig::XML_PATH_WHITELIST, $whiteListConfig, 'default', 0); 80 | } 81 | 82 | public static function loadEnableWithWhitelistAndRedirectCatcherConfiguration() 83 | { 84 | $config = ObjectManager::getInstance()->get(Config::class); 85 | $config->saveConfig(CatcherConfig::XML_PATH_ENABLED, 1, 'default', 0); 86 | $whiteListConfig = implode(',', array_merge(self::$whiteListEmails, self::$whiteListDomains)); 87 | $config->saveConfig(CatcherConfig::XML_PATH_WHITELIST, $whiteListConfig, 'default', 0); 88 | $config->saveConfig(CatcherConfig::XML_PATH_REDIRECT_RECIPIENT, self::$redirectRecipient, 'default', 0); 89 | } 90 | 91 | /** 92 | * @magentoAppIsolation enabled 93 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/enabled 1 94 | */ 95 | public function testCatchEmailsEnabled() 96 | { 97 | $this->assertInstanceOf(MailCatcherTransportProxy::class, $this->getMailTransport(['some-email@test.com'])); 98 | } 99 | 100 | /** 101 | * @magentoAppIsolation enabled 102 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/enabled 0 103 | */ 104 | public function testCatchEmailsDisabled() 105 | { 106 | $this->assertNotInstanceOf(MailCatcherTransportProxy::class, $this->getMailTransport(['some-email@test.com'])); 107 | } 108 | 109 | /** 110 | * @magentoAppIsolation enabled 111 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/enabled 1 112 | */ 113 | public function testCatchAllEmails() 114 | { 115 | foreach (self::$catchEmails as $email) { 116 | /** @var MailCatcherTransportProxy $mailTransport */ 117 | $mailTransport = $this->getMailTransport([$email]); 118 | $this->assertTrue($mailTransport->shouldCatchEmail()); 119 | } 120 | foreach (self::$whiteListEmails as $email) { 121 | /** @var MailCatcherTransportProxy $mailTransport */ 122 | $mailTransport = $this->getMailTransport([$email]); 123 | $this->assertTrue($mailTransport->shouldCatchEmail()); 124 | } 125 | foreach ($this->whiteListEmailsByDomain as $email) { 126 | /** @var MailCatcherTransportProxy $mailTransport */ 127 | $mailTransport = $this->getMailTransport([$email]); 128 | $this->assertTrue($mailTransport->shouldCatchEmail()); 129 | } 130 | } 131 | 132 | /** 133 | * @magentoAppIsolation enabled 134 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/enabled 1 135 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/whitelist whitelist_one@mail.catcher,whitelist_two@mail.catcher,whitelist.catcher 136 | */ 137 | public function testCatchOnlyNotWhitelistedEmails() 138 | { 139 | foreach (self::$catchEmails as $email) { 140 | /** @var MailCatcherTransportProxy $mailTransport */ 141 | $mailTransport = $this->getMailTransport([$email]); 142 | $this->assertTrue($mailTransport->shouldCatchEmail()); 143 | } 144 | foreach (self::$whiteListEmails as $email) { 145 | /** @var MailCatcherTransportProxy $mailTransport */ 146 | $mailTransport = $this->getMailTransport([$email]); 147 | $this->assertFalse($mailTransport->shouldCatchEmail()); 148 | } 149 | foreach ($this->whiteListEmailsByDomain as $email) { 150 | /** @var MailCatcherTransportProxy $mailTransport */ 151 | $mailTransport = $this->getMailTransport([$email]); 152 | $this->assertFalse($mailTransport->shouldCatchEmail()); 153 | } 154 | } 155 | 156 | /** 157 | * @magentoAppIsolation enabled 158 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/enabled 1 159 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/whitelist whitelist_one@mail.catcher,whitelist_two@mail.catcher,whitelist.catcher 160 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/redirect_recipient redirect_recipient@mail.catcher 161 | */ 162 | public function testNotCatchRedirectedEmails() 163 | { 164 | foreach (self::$catchEmails as $email) { 165 | /** @var MailCatcherTransportProxy $mailTransport */ 166 | $mailTransport = $this->getMailTransport([$email]); 167 | $this->assertFalse($mailTransport->shouldCatchEmail()); 168 | $recipients = $mailTransport->getMessage()->getRecipients(); 169 | $this->assertEquals(self::$redirectRecipient, reset($recipients)); 170 | } 171 | foreach (self::$whiteListEmails as $email) { 172 | /** @var MailCatcherTransportProxy $mailTransport */ 173 | $mailTransport = $this->getMailTransport([$email]); 174 | $this->assertFalse($mailTransport->shouldCatchEmail()); 175 | $recipients = $mailTransport->getMessage()->getRecipients(); 176 | $this->assertEquals($email, reset($recipients)); 177 | } 178 | foreach ($this->whiteListEmailsByDomain as $email) { 179 | /** @var MailCatcherTransportProxy $mailTransport */ 180 | $mailTransport = $this->getMailTransport([$email]); 181 | $this->assertFalse($mailTransport->shouldCatchEmail()); 182 | $recipients = $mailTransport->getMessage()->getRecipients(); 183 | $this->assertEquals($email, reset($recipients)); 184 | } 185 | } 186 | 187 | /** 188 | * @magentoAppIsolation enabled 189 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/enabled 1 190 | */ 191 | public function testSeveralCatchAllEmails() 192 | { 193 | /** @var MailCatcherTransportProxy $mailTransport */ 194 | $mailTransport = $this->getMailTransport(self::$catchEmails); 195 | $this->assertTrue($mailTransport->shouldCatchEmail()); 196 | /** @var MailCatcherTransportProxy $mailTransport */ 197 | $mailTransport = $this->getMailTransport(self::$whiteListEmails); 198 | $this->assertTrue($mailTransport->shouldCatchEmail()); 199 | /** @var MailCatcherTransportProxy $mailTransport */ 200 | $mailTransport = $this->getMailTransport($this->whiteListEmailsByDomain); 201 | $this->assertTrue($mailTransport->shouldCatchEmail()); 202 | } 203 | 204 | /** 205 | * @magentoAppIsolation enabled 206 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/enabled 1 207 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/whitelist whitelist_one@mail.catcher,whitelist_two@mail.catcher,whitelist.catcher 208 | */ 209 | public function testSeveralCatchOnlyNotWhitelistedEmails() 210 | { 211 | /** @var MailCatcherTransportProxy $mailTransport */ 212 | $mailTransport = $this->getMailTransport(self::$catchEmails); 213 | $this->assertTrue($mailTransport->shouldCatchEmail()); 214 | 215 | /** @var MailCatcherTransportProxy $mailTransport */ 216 | $mailTransport = $this->getMailTransport(array_merge(self::$whiteListEmails, $this->whiteListEmailsByDomain)); 217 | $this->assertFalse($mailTransport->shouldCatchEmail()); 218 | 219 | /** @var MailCatcherTransportProxy $mailTransport */ 220 | $mailTransport = $this->getMailTransport( 221 | array_merge(self::$whiteListEmails, self::$catchEmails, $this->whiteListEmailsByDomain) 222 | ); 223 | $this->assertTrue($mailTransport->shouldCatchEmail()); 224 | } 225 | 226 | /** 227 | * @magentoAppIsolation enabled 228 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/enabled 1 229 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/whitelist whitelist_one@mail.catcher,whitelist_two@mail.catcher,whitelist.catcher 230 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/redirect_recipient redirect_recipient@mail.catcher 231 | */ 232 | public function testSeveralNotCatchRedirectedEmails() 233 | { 234 | /** @var MailCatcherTransportProxy $mailTransport */ 235 | $mailTransport = $this->getMailTransport(self::$catchEmails); 236 | $this->assertFalse($mailTransport->shouldCatchEmail()); 237 | foreach ($mailTransport->getMessage()->getRecipients() as $recipient) { 238 | $this->assertEquals(self::$redirectRecipient, $recipient); 239 | } 240 | 241 | $allWhiteListedEmails = array_merge(self::$whiteListEmails, $this->whiteListEmailsByDomain); 242 | /** @var MailCatcherTransportProxy $mailTransport */ 243 | $mailTransport = $this->getMailTransport($allWhiteListedEmails); 244 | $this->assertFalse($mailTransport->shouldCatchEmail()); 245 | foreach ($mailTransport->getMessage()->getRecipients() as $recipient) { 246 | $this->assertContains($recipient, $allWhiteListedEmails); 247 | } 248 | 249 | $allWhiteListedEmails = array_merge(self::$whiteListEmails, $this->whiteListEmailsByDomain); 250 | /** @var MailCatcherTransportProxy $mailTransport */ 251 | $mailTransport = $this->getMailTransport(array_merge($allWhiteListedEmails, self::$catchEmails)); 252 | $this->assertFalse($mailTransport->shouldCatchEmail()); 253 | $validEmailsToSend = array_merge($allWhiteListedEmails, [self::$redirectRecipient]); 254 | foreach ($mailTransport->getMessage()->getRecipients() as $recipient) { 255 | $this->assertContains($recipient, $validEmailsToSend); 256 | } 257 | $oneWhitelistedEmail = reset($allWhiteListedEmails); 258 | $this->assertContains($oneWhitelistedEmail, $mailTransport->getMessage()->getRecipients()); 259 | $this->assertContains(self::$redirectRecipient, $mailTransport->getMessage()->getRecipients()); 260 | } 261 | 262 | /** 263 | * @magentoAppIsolation enabled 264 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/enabled 1 265 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/whitelist whitelist_one@mail.catcher,whitelist_two@mail.catcher,whitelist.catcher 266 | */ 267 | public function testCatchCcEmails() 268 | { 269 | foreach (self::$catchEmails as $email) { 270 | /** @var MailCatcherTransportProxy $mailTransport */ 271 | $mailTransport = $this->getMailTransport([$email], [$this->catchCcEmail]); 272 | $this->assertTrue($mailTransport->shouldCatchEmail()); 273 | } 274 | foreach (self::$whiteListEmails as $email) { 275 | /** @var MailCatcherTransportProxy $mailTransport */ 276 | $mailTransport = $this->getMailTransport([$email], [$this->catchCcEmail]); 277 | $this->assertTrue($mailTransport->shouldCatchEmail()); 278 | } 279 | } 280 | 281 | /** 282 | * @magentoAppIsolation enabled 283 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/enabled 1 284 | * @magentoConfigFixture default/staempfli_mailcatcher/configuration/whitelist whitelist_one@mail.catcher,whitelist_two@mail.catcher,whitelist.catcher 285 | */ 286 | public function testCatchBccEmails() 287 | { 288 | foreach (self::$catchEmails as $email) { 289 | /** @var MailCatcherTransportProxy $mailTransport */ 290 | $mailTransport = $this->getMailTransport([$email], [$this->catchBccEmail]); 291 | $this->assertTrue($mailTransport->shouldCatchEmail()); 292 | } 293 | foreach (self::$whiteListEmails as $email) { 294 | /** @var MailCatcherTransportProxy $mailTransport */ 295 | $mailTransport = $this->getMailTransport([$email], [$this->catchBccEmail]); 296 | $this->assertTrue($mailTransport->shouldCatchEmail()); 297 | } 298 | } 299 | 300 | private function getMailTransport(array $recipients, array $cc = [], array $bcc = []): TransportInterface 301 | { 302 | $transport = $this->transportBuilder 303 | ->setTemplateIdentifier(self::TEST_EMAIL_IDENTIFIER) 304 | ->setTemplateOptions(['area' => FrontNameResolver::AREA_CODE, 'store' => Store::DEFAULT_STORE_ID]) 305 | ->setTemplateVars([]) 306 | ->setFrom(['name' => 'integration-tests', 'email' => 'integration-test@mail.catcher']) 307 | ->addTo($recipients); 308 | if ($cc) { 309 | $transport->addCc($cc); 310 | } 311 | if ($bcc) { 312 | $transport->addBcc($bcc); 313 | } 314 | return $transport->getTransport(); 315 | } 316 | 317 | } -------------------------------------------------------------------------------- /Test/Integration/TransportBuilderFake.php: -------------------------------------------------------------------------------- 1 | [ 20 | * 'Magento\Framework\Mail\Template\TransportBuilder' => 21 | * 'Magento\TestFramework\Mail\Template\TransportBuilderMock', 22 | * ] 23 | * 24 | * Because of that, "TransportBuilderMock" is always returned on tests. 25 | * For out tests we need an instance of original "TransportBuilder", so the only way to accomplish that 26 | * is creating this fake class that directly extends from it. 27 | */ 28 | } -------------------------------------------------------------------------------- /Transport/MailCatcherTransportProxy.php: -------------------------------------------------------------------------------- 1 | mailCatcherLogger = $mailCatcherLogger; 48 | $this->message = $message; 49 | $this->originalTransport = $originalTransport; 50 | $this->catcherConfig = $catcherConfig; 51 | $this->mailCatcherRepository = $mailCatcherRepository; 52 | } 53 | 54 | public function getMessage() 55 | { 56 | return $this->message; 57 | } 58 | 59 | public function sendMessage() 60 | { 61 | if ($this->shouldCatchEmail()) { 62 | $this->mailCatcherLogger->addInfo( 63 | "Recipients: " . implode(',', $this->message->getRecipients()) . PHP_EOL . 64 | "Subject: " . $this->message->getSubject() . PHP_EOL . 65 | "Body: " . $this->getBodyAsString() . PHP_EOL 66 | ); 67 | return; 68 | } 69 | return $this->originalTransport->sendMessage(); 70 | } 71 | 72 | /** 73 | * @return bool 74 | */ 75 | public function shouldCatchEmail() 76 | { 77 | if (!$this->catcherConfig->isCatcherEnabled()) { 78 | return false; 79 | } 80 | if ($this->areAllRecipientsAllowed($this->message->getRecipients())) { 81 | return false; 82 | } 83 | return true; 84 | } 85 | 86 | private function areAllRecipientsAllowed(array $recipients): bool 87 | { 88 | foreach ($recipients as $recipient) { 89 | if (!$this->mailCatcherRepository->isRecipientWhiteListed($recipient) && 90 | !$this->mailCatcherRepository->isRedirectRecipient($recipient) 91 | ) { 92 | return false; 93 | } 94 | } 95 | return true; 96 | } 97 | 98 | private function getBodyAsString() 99 | { 100 | $body = $this->message->getBody(); 101 | if ($body instanceof \Zend_Mime_Part) { 102 | return $body->getContent(); 103 | } 104 | return $body; 105 | } 106 | 107 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "staempfli/magento2-module-mailcatcher", 3 | "description": "magento 2 module to catch, log and redirect emails on local and dev", 4 | "keywords": ["magento2", "module", "email", "mail", "catch", "catcher"], 5 | "require": { 6 | "php": "^7.0|^7.1|^7.2", 7 | "magento/framework": "^100.1|^101.0|^102.0" 8 | }, 9 | "type": "magento2-module", 10 | "license": [ 11 | "OSL-3.0", 12 | "AFL-3.0" 13 | ], 14 | "autoload": { 15 | "files": [ 16 | "registration.php" 17 | ], 18 | "psr-4": { 19 | "Staempfli\\MailCatcher\\": "" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /docs/img/mailcatcher_admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/staempfli/magento2-module-mailcatcher/2b169c11b4b1142b55f5eab8c74b824d2db7b64e/docs/img/mailcatcher_admin.png -------------------------------------------------------------------------------- /etc/acl.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /etc/adminhtml/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | staempfli 18 | Staempfli_MailCatcher::configuration 19 | 20 | 21 | 22 | 23 | Magento\Config\Model\Config\Source\Yesno 24 | Enable on Dev servers if you want to catch mails. It should always be disabled on Prod environments 25 | 26 | 27 | 28 | Comma separated list of emails/domains that are not caught 29 | 30 | 1 31 | 32 | 33 | 34 | 35 | validate-email 36 | If set, caught emails will be redirected to this address (i.e something@trash-mail.com). If empty, caught emails will be logged 37 | 38 | 1 39 | 40 | 41 | 42 |
43 |
44 |
-------------------------------------------------------------------------------- /etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 0 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /etc/email_templates.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 |