Browse Source

Merge pull request #29 from yiisoft/27-signature

Added ability to specify message signature
tags/2.0.6
Paul Klimov 9 years ago
parent
commit
2d759ae40c
  1. 2
      CHANGELOG.md
  2. 98
      Message.php
  3. 96
      tests/MessageTest.php

2
CHANGELOG.md

@ -4,7 +4,7 @@ Yii Framework 2 swiftmailer extension Change Log
2.0.6 under development
-----------------------
- no changes in this release.
- Enh #27: Added ability to specify message signature (klimov-paul)
2.0.5 March 17, 2016

98
Message.php

@ -7,6 +7,9 @@
namespace yii\swiftmailer;
use Yii;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
use yii\mail\BaseMessage;
/**
@ -18,6 +21,7 @@ use yii\mail\BaseMessage;
* @method Mailer getMailer() returns mailer instance.
*
* @property \Swift_Message $swiftMessage Swift message instance. This property is read-only.
* @property array|callable|\Swift_Signer $signature message signature. This property is write-only.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
@ -28,6 +32,10 @@ class Message extends BaseMessage
* @var \Swift_Message Swift message instance.
*/
private $_swiftMessage;
/**
* @var \Swift_Signer[] attached signers
*/
private $signers = [];
/**
@ -301,6 +309,96 @@ class Message extends BaseMessage
}
/**
* Sets message signature
* @param array|callable|\Swift_Signer $signature signature specification.
* See [[addSignature()]] for details on how it should be specified.
* @return $this self reference.
* @since 2.0.6
*/
public function setSignature($signature)
{
if (!empty($this->signers)) {
// clear previously set signers
$swiftMessage = $this->getSwiftMessage();
foreach ($this->signers as $signer) {
$swiftMessage->detachSigner($signer);
}
$this->signers = [];
}
return $this->addSignature($signature);
}
/**
* Adds message signature.
* @param array|callable|\Swift_Signer $signature signature specification, this can be:
*
* - [[\Swift_Signer]] instance
* - callable, which returns [[\Swift_Signer]] instance
* - configuration array for the signer creation
*
* @return $this self reference
* @throws InvalidConfigException on invalid signature configuration
* @since 2.0.6
*/
public function addSignature($signature)
{
if ($signature instanceof \Swift_Signer) {
$signer = $signature;
} elseif (is_callable($signature)) {
$signer = call_user_func($signature);
} elseif (is_array($signature)) {
$signer = $this->createSwiftSigner($signature);
} else {
throw new InvalidConfigException('Signature should be instance of "Swift_Signer", callable or array configuration');
}
$this->getSwiftMessage()->attachSigner($signer);
$this->signers[] = $signer;
return $this;
}
/**
* Creates signer from its configuration
* @param array $signature signature configuration
* @return \Swift_Signer signer instance
* @throws InvalidConfigException on invalid configuration provided
* @since 2.0.6
*/
protected function createSwiftSigner($signature)
{
if (!isset($signature['type'])) {
throw new InvalidConfigException('Signature configuration should contain "type" key');
}
switch (strtolower($signature['type'])) {
case 'dkim' :
$domain = ArrayHelper::getValue($signature, 'domain', null);
$selector = ArrayHelper::getValue($signature, 'selector', null);
if (isset($signature['key'])) {
$privateKey = $signature['key'];
} elseif (isset($signature['file'])) {
$privateKey = file_get_contents(Yii::getAlias($signature['file']));
} else {
throw new InvalidConfigException("Either 'key' or 'file' signature option should be specified");
}
return new \Swift_Signers_DKIMSigner($privateKey, $domain, $selector);
case 'opendkim' :
$domain = ArrayHelper::getValue($signature, 'domain', null);
$selector = ArrayHelper::getValue($signature, 'selector', null);
if (isset($signature['key'])) {
$privateKey = $signature['key'];
} elseif (isset($signature['file'])) {
$privateKey = file_get_contents(Yii::getAlias($signature['file']));
} else {
throw new InvalidConfigException("Either 'key' or 'file' signature option should be specified");
}
return new \Swift_Signers_OpenDKIMSigner($privateKey, $domain, $selector);
default:
throw new InvalidConfigException("Unrecognized signature type '{$signature['type']}'");
}
}
/**
* @inheritdoc
*/
public function toString()

96
tests/MessageTest.php

@ -21,6 +21,7 @@ class MessageTest extends TestCase
*/
protected $testEmailReceiver = 'someuser@somedomain.com';
public function setUp()
{
$this->mockApplication([
@ -110,6 +111,24 @@ class MessageTest extends TestCase
return $attachment;
}
/**
* @param Message $message
* @return array list of attached swift signers
*/
protected function getSwiftSigners(Message $message)
{
$swiftMessage = $message->getSwiftMessage();
$reflection = new \ReflectionObject($message->getSwiftMessage());
$headerSignersReflection = $reflection->getProperty('headerSigners');
$headerSignersReflection->setAccessible(true);
$bodySignersReflection = $reflection->getProperty('bodySigners');
$bodySignersReflection->setAccessible(true);
return array_merge(
$headerSignersReflection->getValue($swiftMessage),
$bodySignersReflection->getValue($swiftMessage)
);
}
// Tests :
public function testGetSwiftMessage()
@ -186,6 +205,37 @@ class MessageTest extends TestCase
$this->assertContains('Bcc: ' . $bcc, $messageString, 'Incorrect "Bcc" header!');
}
public function testSetupSignature()
{
$message = new Message();
$message->addSignature([
'type' => 'dkim',
'key' => 'private key',
]);
$signers = $this->getSwiftSigners($message);
$this->assertTrue($signers[0] instanceof \Swift_Signers_DKIMSigner);
$signer = new \Swift_Signers_DKIMSigner('manual', null, null);
$message->addSignature($signer);
$signers = $this->getSwiftSigners($message);
$this->assertSame($signer, $signers[1]);
$signer = new \Swift_Signers_DKIMSigner('callable', null, null);
$message->addSignature(function () use ($signer) {
return $signer;
});
$signers = $this->getSwiftSigners($message);
$this->assertSame($signer, $signers[2]);
$message->setSignature([
'type' => 'dkim',
'key' => 'override',
]);
$signers = $this->getSwiftSigners($message);
$this->assertCount(1, $signers);
}
/**
* @depends testGetSwiftMessage
*/
@ -202,6 +252,52 @@ class MessageTest extends TestCase
/**
* @depends testSend
*/
public function testSendSigned()
{
$privateKey = "-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAyehiMTRxvfQz8nbQQAgL481QipVMF+E7ljWKHTQQSYfqktR+
zFYqX81vKeK9/2D6AiK5KJSBVdF7aURasppuDaxFJWrPvacd3IQCrGxsGkwwlWPO
ggB1WpOEKhVUZnGzdm96Fk23oHFKrEiQlSG0cB9P/wUKz57b8tsaPve5sKBG0Kww
9YIDRM0x4w3c9fupPz8H5p2HHn4uPbn+whJyALZHD1+CftIGOHq8AUH4w4Z7bjF4
DD4zibpgRn96BVaRIJjxZdlKq69v52j3v8O8SAqSkWmpDWiIsm85Gl00Loay6iiJ
XNy11y0sUysFeCSpb/9cRyxb6j0jEwQXrw0J/QIDAQABAoIBAQCFuRgXeKGAalVh
V5mTXwDo7hlSv5C3HCBH2svPjaTf3lnYx033bXYBH2Fpf1fQ5NyQP4kcPEbwnJ48
2N2s/qS2/4qIPpa6CA259+CBbAmo3R8sQf8KkN0okRzudlQAyXtPjINydCSS6ZXI
RwMjEkCcJdDomOFRIuiPjtdyLsXYGRAa95yjpTU0ri1mEJocX6tlchlgUsjwc2ml
rCTKLc6b3KtYNYUZ/Rg0HzWRIhkbQFIz7uS0t7gF3sqDOLcaoWIv2rmrpg5T0suA
e5Sz7nK2XBeaPi/AKNCVoXJiCJ6SU6A+6Q4T5Rvnt+uxGpLKiilb/fRpQaq1RFO9
k5BDPgftAoGBAPyYBPrTPYPYGosqzbFypNaWLOUnjkdFxlThpwvLOa7nzwVcsQ8V
EXDkELNYy/jOYJLsNhhZ+bGAwWdNV46pdurFKuzS4vb11RfZCc3BTM05IFUFrKir
YVgWw5AYKJLkUiACASEP55P8j2cKocCV5SdI0sGyU7W+3S1NbhBOlr0nAoGBAMyh
Y/Ki5wo3LX43l9F1I2HnKVJSj2XzpWTSYco8sUbS4yUBVk9qPBjIHhT+mK2k2FqD
bSWsu5tGVfaMlFbYxXnSBqjIQfHRLWWVmWMr5sLFk0aJyY1mjGh6BEhTp/Xs86/w
cdVlI1N5blxPy4VvoLmHIb/O1xqi64FV1gW7gD47AoGAErFlXPKZENLDVB08z67+
R+shM2wz+U5OmSWB6TuG70y0Y18ysz0J52LZYYxmu+j5+KWGc1LlSZ+PsIdmvWYJ
KOKihJgut7wFoxgqw5FUj7N0kxYyauET+SLmIhnHludStI+xabL1nlwIeMWupsPx
C3E2N6Ns0nxnfdzHEmneee0CgYA5kF0RcIoV8Ze2neTzY0Rk0iZpphf40iWAyz3/
KjukdMa5LjsddAEb54+u0EAa+Phz3eziYEkWUR71kG5aT/idYFvHNy513CYtIXxY
zYzI1dOsUC6GvIZbDZgO0Jm7MMEMiVM8eIsLfGlzRm82RkSsbDsuPf183L/rTj46
tphI6QKBgQDobarzJhVUdME4QKAlhJecKBO1xlVCXWbKGdRcJn0Gzq6iwZKdx64C
hQGpKaZBDDCHLk7dDzoKXF1udriW9EcImh09uIKGYYWS8poy8NUzmZ3fy/1o2C2O
U41eAdnQ3dDGzUNedIJkSh6Z0A4VMZIEOag9hPNYqQXZBQgfobvPKw==
-----END RSA PRIVATE KEY-----
";
$message = $this->createTestMessage();
$message->setTo($this->testEmailReceiver);
$message->setFrom('someuser@somedomain.com');
$message->setSubject('Signed message');
$message->setTextBody('Signed message body');
$message->setSignature([
'type' => 'dkim',
'key' => $privateKey,
]);
$this->assertTrue($message->send());
}
/**
* @depends testSend
*/
public function testAttachFile()
{
$message = $this->createTestMessage();

Loading…
Cancel
Save