diff --git a/.gitignore b/.gitignore index 13b3fba..5ec15ef 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ vendor composer.lock .phpunit.result.cache tests/_report +.env diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 0000000..595f62c --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,67 @@ +setRules([ + '@PSR2' => true, + 'blank_line_after_namespace' => true, + 'class_definition' => true, + 'elseif' => true, + 'encoding' => true, + 'full_opening_tag' => true, + 'function_declaration' => true, + 'indentation_type' => true, + 'lowercase_constants' => true, + 'lowercase_keywords' => true, + 'method_argument_space' => true, + 'no_break_comment' => true, + 'no_closing_tag' => true, + 'no_spaces_after_function_name' => true, + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_extra_blank_lines' => true, + 'align_multiline_comment' => true, + 'array_syntax' => ['syntax' => 'short'], + 'array_indentation' => true, + //'binary_operator_spaces' => true, ('=' is binary operator..) + 'blank_line_after_opening_tag' => true, + 'cast_spaces' => true, + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'concat_space' => ['spacing' => 'one'], + 'explicit_indirect_variable' => true, + 'fully_qualified_strict_types' => true, + 'function_typehint_space' => true, + 'linebreak_after_opening_tag' => true, + 'lowercase_static_reference' => true, + 'no_blank_lines_after_class_opening' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_null_property_initialization' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_useless_return' => true, + 'no_useless_else' => true, + 'no_unused_imports' => true, + 'ordered_imports' => true, + 'ordered_class_elements' => true, + 'single_quote' => true, + 'whitespace_after_comma_in_array' => true, + 'backtick_to_shell_exec' => true, + 'class_attributes_separation' => true, + 'no_superfluous_elseif' => true, + 'ternary_operator_spaces' => true, + 'ternary_to_null_coalescing' => true, + 'trailing_comma_in_multiline_array' => true, + 'trim_array_spaces' => true, + 'space_after_semicolon' => true, + ]) + ->setFinder(PhpCsFixer\Finder::create() + ->exclude('vendor') + ->in(__DIR__) + ) +; diff --git a/composer.json b/composer.json index 870fcf1..b2b6689 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ "laravel/framework": "^5.6.0|^6.0.0" }, "require-dev": { - "orchestra/testbench": "^4.0" + "orchestra/testbench": "^4.0", + "guzzlehttp/guzzle": "^6.4" }, "autoload": { "psr-4": { diff --git a/phpunit.xml b/phpunit.xml index c29661d..bb82292 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -18,6 +18,10 @@ ./tests/Feature + + + ./tests/Integration + diff --git a/src/Config.php b/src/Config.php new file mode 100644 index 0000000..2cee92f --- /dev/null +++ b/src/Config.php @@ -0,0 +1,204 @@ + .., 'name' => .. ] + */ + public function __construct($key) + { + // Retreive email + $this->parseEmail($key); + + $this->loadConfiguration(); + + // If credentials are empty, load default values. + // This makes local testing for many emails + // very convenient. + if ($this->isEmpty()) { + $this->loadDefault(); + } + } + + /** + * Check if log driver is used. + * + * @return boolean + */ + public function isLogDriver() + { + return (isset($this->provider['driver']) && $this->provider['driver'] == 'log'); + } + + /** + * Get provider. + * + * @return array + */ + public function getProvider() + { + return $this->provider; + } + + /** + * Get setting. + * + * @return array + */ + public function getSetting() + { + return $this->settings; + } + + /** + * Return email of sender. + * + * @return string + */ + public function getFromEmail() + { + return $this->settings['from_mail'] ?? $this->email; + } + + /** + * Return name of sender. + * + * @return string + */ + public function getFromName() + { + return $this->name; + } + + /** + * Return email of sender. + * + * @return string + */ + public function getReplyEmail() + { + return $this->settings['reply_to_mail'] ?? null; + } + + /** + * Return name of sender. + * + * @return string + */ + public function getReplyName() + { + return $this->settings['reply_to_name'] ?? null; + } + + /** + * Parse $key into email and possible from name + * + * @param mixed string/array + * @return void + */ + protected function parseEmail($key) + { + if (is_array($key)) { + $this->name = $key['name'] ?? null; + + if (empty($key['email'])) { + throw new Exceptions\InvalidConfigKeyException; + } + $this->email = $key['email']; + } else { + $this->email = $key; + } + } + + /** + * Load config settings and provder from email + * + * @return void + */ + protected function loadConfiguration() + { + try { + $this->settings = config('multimail.emails')[$this->email]; + } catch (\Exception $e) { + throw new Exceptions\EmailNotInConfigException($this->email); + } + + if (empty($this->name)) { + $this->name = $this->settings['from_name'] ?? null; + } + + $this->loadProvider(); + } + + protected function loadProvider() + { + if (isset($this->settings['provider']) && !empty($provider = $this->settings['provider'])) { + $this->provider = config('multimail.provider.' . $provider); + } + + if (empty($this->provider)) { + $this->provider = config('multimail.provider.default'); + } + } + + /** + * Check if email, pass and username are not empty + * + * @return boolean + */ + protected function isEmpty() + { + return (empty($this->email) || empty($this->settings) || empty($this->settings['pass']) || empty($this->settings['username'])); + } + + /** + * Load default setting. If default setting is + * invalid throw exception + * + * @return void + */ + protected function loadDefault() + { + $this->settings = config('multimail.emails.default'); + + $this->loadProvider(); + + if ($this->provider['driver'] != 'log' && (empty($this->settings) || empty($this->settings['pass']) || empty($this->settings['username']))) { + throw new Exceptions\NoDefaultException($this->email); + } + } +} diff --git a/src/Exceptions/EmailNotInConfigException.php b/src/Exceptions/EmailNotInConfigException.php new file mode 100644 index 0000000..05530d8 --- /dev/null +++ b/src/Exceptions/EmailNotInConfigException.php @@ -0,0 +1,12 @@ +message = 'Email ' . $mail . ' not found in config/multimail.php!'; + parent::__construct(); + } +} diff --git a/src/Exceptions/InvalidConfigKeyException.php b/src/Exceptions/InvalidConfigKeyException.php new file mode 100644 index 0000000..c26c36d --- /dev/null +++ b/src/Exceptions/InvalidConfigKeyException.php @@ -0,0 +1,12 @@ +message = "Mailer name has to be provided in array as column 'email'"; + parent::__construct(); + } +} diff --git a/src/Exceptions/NoDefaultException.php b/src/Exceptions/NoDefaultException.php new file mode 100644 index 0000000..b85b990 --- /dev/null +++ b/src/Exceptions/NoDefaultException.php @@ -0,0 +1,12 @@ +message = 'Username or password for ' . $mail . ' is missing in config/multimail.php and no default specified!'; + parent::__construct(); + } +} diff --git a/src/MultiMailer.php b/src/MultiMailer.php index a2e2ee5..c7d6343 100644 --- a/src/MultiMailer.php +++ b/src/MultiMailer.php @@ -5,18 +5,50 @@ use \Illuminate\Mail\Mailer; use Illuminate\Contracts\Mail\Mailable as MailableContract; use Illuminate\Mail\Mailable; -use Illuminate\Mail\Transport\LogTransport; -use Psr\Log\LoggerInterface; use Swift_Mailer; -use Swift_SmtpTransport; +use Swift_Plugins_AntiFloodPlugin; class MultiMailer { - protected $mailer; + /** + * Plugins for Swift_Mailer + * @var array + */ + protected static $plugins; - protected $locale; + /** + * Create mailer from config/multimail.php + * If its not a log driver, add AntiFloodPlugin. + * + * @param mixed $key string or array + * @param int timeout + * @param int frequency + * @return \Illuminate\Mail\Mailer + */ + public static function getMailer($key, $timeout = null, $frequency = null) + { + $config = new Config($key); - protected static $plugins; + $swift_mailer = static::getSwiftMailer($config); + + if (!$config->isLogDriver() && !empty($timeout) && !empty($frequency)) { + static::$plugins[] = new Swift_Plugins_AntiFloodPlugin($frequency, $timeout); + } + + static::registerPlugins($swift_mailer); + + $view = app()->get('view'); + $events = app()->get('events'); + $mailer = new Mailer($view, $swift_mailer, $events); + + $mailer->alwaysFrom($config->getFromEmail(), $config->getFromName()); + + if (!empty($reply_mail = $config->getReplyEmail())) { + $mailer->alwaysReplyTo($reply_mail, $config->getReplyEmail()); + } + + return $mailer; + } /** * Send mail throug mail account form $mailer_name @@ -35,9 +67,29 @@ public static function sendMail(MailableContract $mailable, $mailer_name) $mailable->send($mailer); } + /** + * [registerPlugin description] + * @param [type] $plugin [description] + * @return [type] [description] + */ public static function registerPlugin($plugin) { - static::$plugins[] =$plugin; + static::$plugins[] = $plugin; + } + + /** + * [registerPlugin description] + * @param [type] $plugin [description] + * @return [type] [description] + */ + public static function clearPlugins() + { + static::$plugins = []; + } + + public static function getPlugins() + { + return static::$plugins; } public static function queueMail(MailableContract $mailable, $mailer_name) @@ -49,58 +101,6 @@ public static function queueMail(MailableContract $mailable, $mailer_name) Jobs\SendMailJob::dispatch($mailer_name, $mailable); } - /** - * Create mailer from config/multimail.php - * @param mixed $name string or array - * @param int timeout - * @param int frequency - * @return \Illuminate\Mail\Mailer - */ - public static function getMailer($key, $timeout = null, $frequency = null) - { - if (is_array($key)) { - $from_name = $key['name'] ?? null; - - if (empty($key['email'])) { - throw new \Exception("Mailer name has to be provided in array as column 'email' ", 1); - } - $email = $key['email']; - } else { - $email = $key; - } - - $config = config('multimail.emails')[$email]; - - if (empty($email) || empty($config) || empty($config['pass']) || empty($config['username'])) { - $config = config('multimail.emails.default'); - - $provider = static::getProvider($config['provider'] ?? null); - - if ($provider['driver'] != 'log' && (empty($config) || empty($config['pass']) || empty($config['username']))) { - // No need for pass/username when using log-driver - throw new \Exception('Configuration for email: ' . $email . ' is missing in config/multimail.php and no default is specified.', 1); - } - } - - $swift_mailer = static::getSwiftMailer($config, $timeout = null, $frequency = null); - - $view = app()->get('view'); - $events = app()->get('events'); - $mailer = new Mailer($view, $swift_mailer, $events); - - if (empty($from_name) && !empty($config['from_name'])) { - $from_name = $config['from_name']; - } - - $mailer->alwaysFrom($config['from_mail'] ?? $email, $from_name ?? null); - - if (!empty($config['reply_to_mail'])) { - $mailer->alwaysReplyTo($config['reply_to_mail'], $config['reply_to_name'] ?? null); - } - - return $mailer; - } - /** * Begin the process of mailing a mailable class instance. * @@ -178,29 +178,6 @@ public function queue(Mailable $mailable) return (new PendingMail())->queue($mailable); } - /** - * Get SMTP Transport - * @param array - * @return Swift_SmtpTransport - */ - protected static function getSMTPTransport($config, $provider) - { - $transport = new Swift_SmtpTransport($provider['host'], $provider['port'], $provider['encryption']); - $transport->setUsername($config['username']); - $transport->setPassword($config['pass']); - - return $transport; - } - - /** - * Get LOG Transport - * @return LogTransport - */ - protected static function getLogTransport() - { - return new LogTransport(app()->make(LoggerInterface::class)); - } - /** * Create SwiftMailer with timeout/frequency. Timeout/frequency is ignored * when Log Driver is used. @@ -208,51 +185,25 @@ protected static function getLogTransport() * @param array * @return Swift_Mailer */ - public static function getSwiftMailer($config, $timeout = null, $frequency = null) + protected static function getSwiftMailer($config) { - $provider = static::getProvider($config['provider'] ?? null); - - if (isset($provider['driver']) && $provider['driver'] == 'log') { - $transport = static::getLogTransport(); - - $swift_mailer = new Swift_Mailer($transport); - } - else{ - $transport = static::getSMTPTransport($config, $provider); + if ($config->isLogDriver()) { + $transport = TransportManager::createLogDriver(); - $swift_mailer = new Swift_Mailer($transport); - - if (!empty($frequency) && !empty($timeout)) { - $swift_mailer->registerPlugin(new \Swift_Plugins_AntiFloodPlugin($frequency, $timeout)); - } - } - - if(!empty(self::$plugins)){ - foreach (self::$plugins as $plugin) { - $swift_mailer->registerPlugin($plugin); - } + return new Swift_Mailer($transport); } + $transport = TransportManager::createSmtpDriver($config); - return $swift_mailer; + return new Swift_Mailer($transport); } - /** - * Get array of provdier (Host/Port/Encyption/Driver). - * If no provider specified, use default. - * @param string provider - * @return array - */ - protected static function getProvider($provider = null) + protected static function registerPlugins($swift_mailer) { - if (!empty($provider)) { - $provider = config('multimail.provider.' . $provider); - - if (!empty($provider)) { - return $provider; + if (!empty(static::$plugins)) { + foreach (static::$plugins as $plugin) { + $swift_mailer->registerPlugin($plugin); } } - - return config('multimail.provider.default'); } } diff --git a/src/TransportManager.php b/src/TransportManager.php new file mode 100644 index 0000000..f8b3f88 --- /dev/null +++ b/src/TransportManager.php @@ -0,0 +1,38 @@ +getProvider(); + $setting = $config->getSetting(); + + $transport = new Swift_SmtpTransport($provider['host'], $provider['port'], $provider['encryption']); + $transport->setUsername($setting['username']); + $transport->setPassword($setting['pass']); + + return $transport; + } + + /** + * Create LOG Transport. + * + * @return LogTransport + */ + public static function createLogDriver() + { + return new LogTransport(app()->make(LoggerInterface::class)); + } +} diff --git a/tests/.env.example b/tests/.env.example new file mode 100644 index 0000000..e82fe31 --- /dev/null +++ b/tests/.env.example @@ -0,0 +1,10 @@ +MAIL_DRIVER_SMTP=smtp +MAIL_HOST_SMTP=smtp.mailtrap.io +MAIL_PORT_SMTP=2525 + +MAIL_USERNAME_SMTP= +MAIL_PASSWORD_SMTP= +MAIL_ENCRYPTION_SMTP=TLS + +MAILTRAP_API_KEY = +MAILTRAP_INBOX_ID = diff --git a/tests/Unit/Fixtures/view.blade.php b/tests/Fixtures/view.blade.php similarity index 100% rename from tests/Unit/Fixtures/view.blade.php rename to tests/Fixtures/view.blade.php diff --git a/tests/Integration/MultiMailTest.php b/tests/Integration/MultiMailTest.php new file mode 100644 index 0000000..cc42f58 --- /dev/null +++ b/tests/Integration/MultiMailTest.php @@ -0,0 +1,144 @@ +cc($cc) + ->locale($locale) + ->from($from) + ->bcc($bcc) + ->send(new TestMail()); + + $this->assertNotNull($this->emails); + $this->assertEquals(1, count($this->emails)); + } + + /** @test */ + public function send_mail_directly() + { + MultiMail::send(new TestMailIncludingFrom()); + + $this->assertNotNull($this->emails); + $this->assertEquals(1, count($this->emails)); + } + + /** @test */ + public function send_mail_implementing_queue() + { + MultiMail::send(new QueueTestMailIncludingFrom()); + + $this->assertNotNull($this->emails); + $this->assertEquals(1, count($this->emails)); + } + + /** @test */ + public function send_mail_through_queue() + { + MultiMail::queue(new TestMailIncludingFrom()); + + $this->assertNotNull($this->emails); + $this->assertEquals(1, count($this->emails)); + } + + /** @test */ + public function send_mail_through_default() + { + MultiMail::send(new TestMail()); + + $this->assertNotNull($this->emails); + $this->assertEquals(1, count($this->emails)); + } + + /** @test */ + public function send_mail_through_queue_default() + { + MultiMail::queue(new TestMail()); + + $this->assertNotNull($this->emails); + $this->assertEquals(1, count($this->emails)); + } + + /** + * Define environment setup. + * + * @param \Illuminate\Foundation\Application $app + * @return void + */ + protected function getEnvironmentSetUp($app) + { + + // Setup default database to use sqlite :memory: + $app['config']->set('multimail.emails', + ['test@fake.de' => [ + 'pass' => 'fakepass', + 'username' => 'fakeusername', + 'from' => 'Who knows', + 'reply_to_mail' => 'bs@web.de', + ]]); + + $app['config']->set('multimail.provider.default', [ + 'driver' => 'log', + ]); + + $app['config']->set('mail.driver', 'log'); + + View::addLocation(__DIR__ . '/../Fixtures'); + } +} + +class TestMailIncludingFrom extends Mailable +{ + public function __construct() + { + $this->fromMailer = MultiMailTest::FROM; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + $this->subject = 'TestMail Subject'; + return $this->view('view'); + } +} + +class QueueTestMailIncludingFrom extends Mailable implements ShouldQueue +{ + public function __construct() + { + $this->fromMailer = MultiMailTest::FROM; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + $this->subject = 'TestMail Subject'; + return $this->view('view'); + } +} diff --git a/tests/Integration/SMPTTest.php b/tests/Integration/SMPTTest.php new file mode 100644 index 0000000..2f4ba72 --- /dev/null +++ b/tests/Integration/SMPTTest.php @@ -0,0 +1,73 @@ +locale($locale) + ->from($from) + ->send(new TestMail()); + + $this->assertTrue($this->messageExists('TestMail Subject')); + + $this->emptyInbox(); + } + + /** @test */ + public function get_mailer_with_antifloodplugin() + { + $mailer = MultiMail::getMailer(static::FROM, 1, 1); + + $this->assertEquals(2, count(MultiMail::getPlugins())); + } + + /** + * Define environment setup. + * + * @param \Illuminate\Foundation\Application $app + * @return void + */ + protected function getEnvironmentSetUp($app) + { + $app->useEnvironmentPath(__DIR__ . '/..'); + $app->bootstrapWith([LoadEnvironmentVariables::class]); + + parent::getEnvironmentSetUp($app); + + // Setup default database to use sqlite :memory: + $app['config']->set('multimail.emails', + ['smtp@fake.de' => [ + 'pass' => env('MAIL_PASSWORD_SMTP'), + 'username' => env('MAIL_USERNAME_SMTP'), + 'from' => 'Adam Nielsen', + 'provider' => 'smtp', + ]]); + + $app['config']->set('multimail.provider.smtp', [ + 'host' => env('MAIL_HOST_SMTP'), + 'port' => env('MAIL_PORT_SMTP'), + 'encryption' => env('MAIL_ENCRYPTION_SMTP'), + 'driver' => env('MAIL_DRIVER_SMTP'), + ]); + + View::addLocation(__DIR__ . '/../Fixtures'); + } +} diff --git a/tests/Integration/TestMail.php b/tests/Integration/TestMail.php new file mode 100644 index 0000000..a4ac036 --- /dev/null +++ b/tests/Integration/TestMail.php @@ -0,0 +1,19 @@ +subject = 'TestMail Subject'; + return $this->view('view'); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index acb3d31..94f4764 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -5,6 +5,7 @@ use IWasHereFirst2\LaravelMultiMail\Facades\MultiMail; use IWasHereFirst2\LaravelMultiMail\MultiMailServiceProvider; +use Mail; use Swift_Events_EventListener; use Swift_Message; @@ -16,7 +17,10 @@ public function setUp(): void { parent::setUp(); + MultiMail::clearPlugins(); MultiMail::registerPlugin(new TestingMailEventListener($this)); + Mail::getSwiftMailer() + ->registerPlugin(new TestingMailEventListener($this)); } public function addEmail(Swift_Message $email) @@ -34,24 +38,6 @@ protected function getPackageProviders($app) { return [MultiMailServiceProvider::class]; } - - /** - * Define environment setup. - * - * @param \Illuminate\Foundation\Application $app - * @return void - */ - protected function getEnvironmentSetUp($app) - { - - // Setup default database to use sqlite :memory: - $app['config']->set('database.default', 'testbench'); - $app['config']->set('database.connections.testbench', [ - 'driver' => 'sqlite', - 'database' => ':memory:', - 'prefix' => '', - ]); - } } class TestingMailEventListener implements Swift_Events_EventListener @@ -63,6 +49,11 @@ public function __construct($test) $this->test = $test; } + public function getDebugInfo() + { + return 'This is the Custom Test Case Event Plugin'; + } + public function beforeSendPerformed($event) { $this->test->addEmail($event->getMessage()); diff --git a/tests/Traits/MailTrap.php b/tests/Traits/MailTrap.php new file mode 100644 index 0000000..b502d9e --- /dev/null +++ b/tests/Traits/MailTrap.php @@ -0,0 +1,210 @@ + + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +namespace IWasHereFirst2\LaravelMultiMail\Tests\Traits; + +use \Exception; +use GuzzleHttp\Client; +use Illuminate\Support\Facades\Config; + +trait MailTrap +{ + /** + * The MailTrap configuration. + * + * @var integer + */ + protected $mailTrapInboxId; + + /** + * The MailTrap API Key. + * + * @var string + */ + protected $mailTrapApiKey; + + /** + * The Guzzle client. + * + * @var Client + */ + protected $client; + + /** + * + * Empty the MailTrap inbox. + * + * @AfterScenario @mail + */ + public function emptyInbox() + { + $this->requestClient()->patch($this->getMailTrapCleanUrl()); + } + + /** + * Get the configuration for MailTrap. + * + * @param integer|null $inboxId + * @throws Exception + */ + protected function applyMailTrapConfiguration($inboxId = null) + { + $this->mailTrapInboxId = env('MAILTRAP_INBOX_ID'); + $this->mailTrapApiKey = env('MAILTRAP_API_KEY'); + } + + /** + * Fetch a MailTrap inbox. + * + * @param integer|null $inboxId + * @return mixed + * @throws RuntimeException + */ + protected function fetchInbox($inboxId = null) + { + if (! $this->alreadyConfigured()) { + $this->applyMailTrapConfiguration($inboxId); + } + + $body = $this->requestClient() + ->get($this->getMailTrapMessagesUrl()) + ->getBody(); + + return $this->parseJson($body); + } + + /** + * Get the MailTrap messages endpoint. + * + * @return string + */ + protected function getMailTrapMessagesUrl() + { + return "/api/v1/inboxes/{$this->mailTrapInboxId}/messages"; + } + + /** + * Get the MailTrap "empty inbox" endpoint. + * + * @return string + */ + protected function getMailTrapCleanUrl() + { + return "/api/v1/inboxes/{$this->mailTrapInboxId}/clean"; + } + + /** + * Determine if MailTrap config has been retrieved yet. + * + * @return boolean + */ + protected function alreadyConfigured() + { + return $this->mailTrapApiKey; + } + + /** + * Request a new Guzzle client. + * + * @return Client + */ + protected function requestClient() + { + if (! $this->client) { + $this->client = new Client([ + 'base_uri' => 'https://mailtrap.io', + 'headers' => ['Api-Token' => $this->mailTrapApiKey], + ]); + } + + return $this->client; + } + + /** + * @param $body + * @return array|mixed + * @throws RuntimeException + */ + protected function parseJson($body) + { + $data = json_decode((string) $body, true); + + if (JSON_ERROR_NONE !== json_last_error()) { + throw new RuntimeException('Unable to parse response body into JSON: ' . json_last_error()); + } + + return $data === null ? [] : $data; + } + + /** + * Search Messages Url + * + * @param string $query Search query + * @return string + */ + protected function searchInboxMessagesUrl($query) + { + return "/api/v1/inboxes/{$this->mailTrapInboxId}/messages?search=" . $query; + } + + /** + * Find and fetch a Message By Query. + * + * @param integer $query Query + * @return mixed + * @throws RuntimeException + */ + protected function findMessage($query) + { + if (! $this->alreadyConfigured()) { + $this->applyMailTrapConfiguration(); + } + + $body = $this->requestClient() + ->get($this->searchInboxMessagesUrl($query)) + ->getBody(); + + return $this->parseJson($body); + } + + /** + * Check if a message exists based on a string query. + * + * @param string $query Query string + * @return mixed + * @throws RuntimeException + */ + protected function messageExists($query) + { + $messages = $this->findMessage($query); + + return count($messages) > 0; + } +} diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php new file mode 100644 index 0000000..ec2ec43 --- /dev/null +++ b/tests/Unit/ConfigTest.php @@ -0,0 +1,105 @@ +expectException(EmailNotInConfigException::class); + + new Config('unknown key'); + } + + /** @test */ + public function create_config_with_invalid_array_key() + { + $this->expectException(InvalidConfigKeyException::class); + + new Config(['unknown key']); + } + + /** @test */ + public function create_config_with_valid_key() + { + $config = new Config(['name' => 'Adam', 'email' => 'test@fake.de']); + + $this->assertEquals('test@fake.de', $config->getFromEmail()); + } + + /** @test */ + /* + public function test_non_existing_mail() + { + $this->expectException(\Exception::class); + $config = new Config(['name' => 'Adam', 'email' => 'test@faki.de']); + }*/ + + /** @test */ + public function get_reply_name() + { + $config = new Config(['name' => 'Adam', 'email' => 'test@fake.de']); + + $this->assertEquals('max', $config->getReplyName()); + } + + /** @test */ + public function load_invalid_default() + { + $this->expectException(NoDefaultException::class); + $config = new Config(['name' => 'Adam', 'email' => 'test@empty.de']); + } + + /** @test */ + public function load_valid_default() + { + app()['config']->set('multimail.emails.default', + [ + 'pass' => 'fakepass', + 'username' => 'fakeusername', + 'from' => 'Who knows', + 'reply_to_mail' => 'bs@web.de', + 'reply_to_name' => 'max', + ]); + + app()['config']->set('multimail.provider.default', [ + 'driver' => 'log', + ]); + + $config = new Config(['name' => 'Adam', 'email' => 'test@empty.de']); + + $this->assertNotNull($config); + } + + /** + * Define environment setup. + * + * @param \Illuminate\Foundation\Application $app + * @return void + */ + protected function getEnvironmentSetUp($app) + { + $app['config']->set('multimail.emails', + ['test@fake.de' => [ + 'pass' => 'fakepass', + 'username' => 'fakeusername', + 'from' => 'Who knows', + 'reply_to_mail' => 'bs@web.de', + 'reply_to_name' => 'max', + ], + 'test@empty.de' => [ + 'pass' => '', + 'username' => '', + 'from' => 'Who knows', + 'reply_to_mail' => 'bs@web.de', + 'reply_to_name' => 'max', + ], ]); + } +} diff --git a/tests/Unit/MultiMailTest.php b/tests/Unit/MultiMailTest.php index 34d13ff..7c664d1 100644 --- a/tests/Unit/MultiMailTest.php +++ b/tests/Unit/MultiMailTest.php @@ -2,66 +2,27 @@ namespace IWasHereFirst2\LaravelMultiMail\Tests\Unit; -use Illuminate\Mail\Mailable; -use Illuminate\Support\Facades\View; use IWasHereFirst2\LaravelMultiMail\Facades\MultiMail; +use IWasHereFirst2\LaravelMultiMail\PendingMail; use IWasHereFirst2\LaravelMultiMail\Tests\TestCase; class MultiMailTest extends TestCase { - const FROM = 'test@fake.de'; - /** @test */ - public function check_if_mail_is_sendable() + public function check_if_multi_chaining_works() { $to = 'test@bar.com'; $cc = 'foo@bar.ur'; $locale = 'de'; - $from = static::FROM; + $from = 'exampli@foo.cc'; $bcc = ['oki@foo.berlin', 'rooky@mooky.de']; - $pendingMail = MultiMail::to($to) - ->cc($cc) - ->locale($locale) - ->from($from) - ->bcc($bcc) - ->send(new TestMail()); - $this->assertEquals(1, count($this->emails)); - } + $classes = []; - /** - * Define environment setup. - * - * @param \Illuminate\Foundation\Application $app - * @return void - */ - protected function getEnvironmentSetUp($app) - { + $classes[] = MultiMail::from('dummy'); + $classes[] = MultiMail::cc('dummy'); + $classes[] = MultiMail::bcc('dummy'); - // Setup default database to use sqlite :memory: - $app['config']->set('multimail.emails', - ['test@fake.de' => [ - 'pass' => 'fakepass', - 'username' => 'fakeusername', - 'from' => 'Who knows', - ]]); - $app['config']->set('multimail.provider.default', [ - 'driver' => 'log', - ]); - - View::addLocation(__DIR__ . '/Fixtures'); - } -} - -class TestMail extends Mailable -{ - /** - * Build the message. - * - * @return $this - */ - public function build() - { - return $this->view('view'); + $this->assertContainsOnlyInstancesOf(PendingMail::class, $classes); } }