Skip to content

Commit

Permalink
feat: batch sending
Browse files Browse the repository at this point in the history
  • Loading branch information
mikejpeters committed Oct 28, 2020
1 parent 99625a7 commit 3fed72c
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 25 deletions.
46 changes: 35 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,47 @@ Yii::$app->mailer->compose('contact/html', ['contactForm' => $form])
->send();
```

You can also specify recipient names and/or perform [batch sending](https://documentation.mailgun.com/en/latest/user_manual.html#batch-sending):
You can also specify an array of addresses and/or speicfy names:

```php
$message->setTo(['[email protected]' => 'Bob']);
```

> **Warning**: By default all recipients' email address will show up in the `to` field for each recipient.
> Enable batch sending to avoid this.
### Batch Sending

When [batch sending](https://documentation.mailgun.com/en/latest/user_manual.html#batch-sending) is enabled,
Mailgun sends each recipient an individual email with only their email in the `to` field.

To use batch sending, set the `messageClass` to `boundstate\mailgun\BatchMessage` in your application configuration:

```php
$message->setTo([
'[email protected]' => [
'id': 3,
'full_name' => 'Bob'
],
'[email protected]' => [
'id': 4,
'full_name' => 'Jane'
],
]);
'mailer' => [
'class' => 'boundstate\mailgun\Mailer',
'messageClass' => 'boundstate\mailgun\BatchMessage',
// ...
]
```

Composing a batch email is similar to regular emails,
except you may define and use recipient variables:

```php
Yii::$app->mailer->compose('hello')
->setTo([
'[email protected]' => [
'id': 3,
'full_name' => 'Bob'
],
'[email protected]' => [
'id': 4,
'full_name' => 'Jane'
],
])
->setSubject('Hi %recipient.full_name%')
->send();
```


Expand Down
56 changes: 56 additions & 0 deletions src/BatchMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
namespace boundstate\mailgun;


use Yii;
use Mailgun\Message\BatchMessage as BatchMessageBuilder;
use yii\base\Exception;

/**
* BatchMessage implements a message class based on Mailgun.
*/
class BatchMessage extends Message
{
/**
* @var Mailer the mailer instance that created this message.
* For independently created messages this is `null`.
*/
public $mailer;

/**
* @var BatchMessageBuilder Mailgun batch message.
*/
private $_batchMessageBuilder;

/**
* @return BatchMessageBuilder Mailgun message builder.
*/
public function getMessageBuilder()
{
if (!is_object($this->_batchMessageBuilder)) {
$this->_batchMessageBuilder = $this->createMessageBuilder();
}

return $this->_batchMessageBuilder;
}

/**
* Send any remaining recipients still in the buffer.
*/
public function finalize() {
$this->$this->getMessageBuilder()->finalize();
}

/**
* Creates the Mailgun message builder.
* @return BatchMessageBuilder message builder.
* @throws Exception if mailer is not an instance of Mailer (i.e. independently created messages)
*/
protected function createMessageBuilder()
{
if (!($this->mailer instanceof Mailer)) {
throw new Exception('BatchMessage must be created from the Mailgun Mailer');
}
return $this->mailer->getMailgun()->messages()->getBatchMessage($this->mailer->domain, false);
}
}
12 changes: 8 additions & 4 deletions src/Mailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,14 @@ protected function sendMessage($message)
{
Yii::info('Sending email', __METHOD__);

$this->getMailgun()->messages()->send(
$this->domain,
$message->getMessageBuilder()->getMessage()
);
if ($message instanceof BatchMessage) {
$message->getMessageBuilder()->finalize();
} else {
$this->getMailgun()->messages()->send(
$this->domain,
$message->getMessageBuilder()->getMessage()
);
}

return true;
}
Expand Down
76 changes: 76 additions & 0 deletions tests/BatchMessageTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php
namespace boundstate\mailgun\tests;

use Yii;

final class BatchMessageTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();

$this->mockApplication([
'components' => [
'mailer' => [
'class' => 'boundstate\mailgun\Mailer',
'messageClass' => 'boundstate\mailgun\BatchMessage',
'key' => getenv('MAILGUN_KEY'),
'domain' => getenv('MAILGUN_DOMAIN'),
],
]
]);
}

public function testCompose(): void
{
$message = Yii::$app->mailer->compose('example', ['name' => 'John']);
$html = $message->getMessageBuilder()->getMessage()['html'];

$this->assertEquals('<p>Hi John!</p>', $html);
}

public function testSingleTo(): void
{
$message = Yii::$app->mailer->compose('example', ['name' => 'John'])
->setTo('[email protected]');
$this->assertEquals(['[email protected]'], $message->getTo());
}

public function testMultiTo(): void
{
$message = Yii::$app->mailer->compose('example', ['name' => 'John'])
->setTo(['[email protected]', '[email protected]']);
$this->assertEquals(['[email protected]', '[email protected]'], $message->getTo());
}

public function testMultiToWithNames(): void
{
$message = Yii::$app->mailer->compose('example', ['name' => 'John'])
->setTo([
'[email protected]' => 'Anne',
'[email protected]' => 'Billy'
]);
$this->assertEquals(['"Anne" <[email protected]>', '"Billy" <[email protected]>'], $message->getTo());
}

public function testMultiToWithVariables(): void
{
$message = Yii::$app->mailer->compose('example', ['name' => 'John'])
->setTo([
'[email protected]' => ['full_name' => 'Anne', 'id' => 3],
'[email protected]' => ['full_name' => 'Billy', 'id' => 4]
]);
$this->assertEquals(['"Anne" <[email protected]>', '"Billy" <[email protected]>'], $message->getTo());
}

public function testSend(): void
{
$message = Yii::$app->mailer->compose('example', ['name' => 'John'])
->setTo(getenv('TEST_RECIPIENT'))
->setFrom('[email protected]')
->setSubject('Test')
->setTestMode(true);

$this->assertTrue($message->send());
}
}
10 changes: 0 additions & 10 deletions tests/MessageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,6 @@ public function testMultiToWithNames(): void
$this->assertEquals(['"Anne" <[email protected]>', '"Billy" <[email protected]>'], $message->getTo());
}

public function testMultiToWithVariables(): void
{
$message = Yii::$app->mailer->compose('example', ['name' => 'John'])
->setTo([
'[email protected]' => ['full_name' => 'Anne', 'id' => 3],
'[email protected]' => ['full_name' => 'Billy', 'id' => 4]
]);
$this->assertEquals(['"Anne" <[email protected]>', '"Billy" <[email protected]>'], $message->getTo());
}

public function testSend(): void
{
$message = Yii::$app->mailer->compose('example', ['name' => 'John'])
Expand Down

0 comments on commit 3fed72c

Please sign in to comment.