mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N°2435.6 Add .gitignore to remove non necessary folders from dependancies (eg. examples, tests, docs, ...)
This commit is contained in:
28
lib/.gitignore
vendored
Normal file
28
lib/.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# TCPDF
|
||||
/combodo/tcpdf/examples
|
||||
/combodo/tcpdf/tools
|
||||
/combodo/tcpdf/fonts
|
||||
!/combodo/tcpdf/fonts/courier*
|
||||
!/combodo/tcpdf/fonts/dejavusans*
|
||||
!/combodo/tcpdf/fonts/droidsansfallback*
|
||||
!/combodo/tcpdf/fonts/helvetica*
|
||||
!/combodo/tcpdf/fonts/symbol.php
|
||||
!/combodo/tcpdf/fonts/times*
|
||||
!/combodo/tcpdf/fonts/zapfdingbats.php
|
||||
|
||||
# Emogrifier
|
||||
/pelago/emogrifier/.github
|
||||
/pelago/emogrifier/tests
|
||||
|
||||
# SCSSPHP
|
||||
/scssphp/scssphp/example
|
||||
|
||||
# SwiftMailer
|
||||
/swiftmailer/swiftmailer/.github
|
||||
/swiftmailer/swiftmailer/doc
|
||||
/swiftmailer/swiftmailer/tests
|
||||
|
||||
# TWIG
|
||||
/twig/twig/doc
|
||||
/twig/twig/test
|
||||
/twig/twig/drupal_test.sh
|
||||
129
lib/pelago/emogrifier/.github/CONTRIBUTING.md
vendored
129
lib/pelago/emogrifier/.github/CONTRIBUTING.md
vendored
@@ -1,129 +0,0 @@
|
||||
# Contributing to Emogrifier
|
||||
|
||||
Those that wish to contribute bug fixes, new features, refactorings and
|
||||
clean-up to Emogrifier are more than welcome.
|
||||
|
||||
When you contribute, please take the following things into account:
|
||||
|
||||
|
||||
## Contributor Code of Conduct
|
||||
|
||||
Please note that this project is released with a
|
||||
[Contributor Code of Conduct](../CODE_OF_CONDUCT.md). By participating in this
|
||||
project, you agree to abide by its terms.
|
||||
|
||||
|
||||
## General workflow
|
||||
|
||||
This is the workflow for contributing changes to Emogrifier:
|
||||
|
||||
1. [Fork the Emogrifier Git repository](https://guides.github.com/activities/forking/).
|
||||
2. Clone your forked repository and
|
||||
[install the development dependencies](#install-the-development-dependencies).
|
||||
3. Add a local remote "upstream" so you will be able to
|
||||
[synchronize your fork with the original Emogrifier repository](https://help.github.com/articles/syncing-a-fork/).
|
||||
4. Create a local branch for your changes.
|
||||
5. [Add unit tests for your changes](#unit-test-your-changes).
|
||||
These tests should fail without your changes.
|
||||
6. Add your changes. Your added unit tests now should pass, and no other tests
|
||||
should be broken. Check that your changes follow the same
|
||||
[coding style](#coding-style) as the rest of the project.
|
||||
7. Add a changelog entry.
|
||||
8. [Commit](#git-commits) and push your changes.
|
||||
9. [Create a pull request](https://help.github.com/articles/about-pull-requests/)
|
||||
for your changes. Check that the Travis build is green. (If it is not, fix the
|
||||
problems listed by Travis.)
|
||||
10. [Request a review](https://help.github.com/articles/about-pull-request-reviews/)
|
||||
from @oliverklee.
|
||||
11. Together with him, polish your changes until they are ready to be merged.
|
||||
|
||||
|
||||
## About code reviews
|
||||
|
||||
After you have submitted a pull request, the Emogrifier team will review your
|
||||
changes. This will probably result in quite a few comments on ways to improve
|
||||
your pull request. The Emogrifier project receives contributions from
|
||||
developers around the world, so we need the code to be the most consistent,
|
||||
readable, and maintainable that it can be.
|
||||
|
||||
Please do not feel frustrated by this - instead please view this both as our
|
||||
contribution to your pull request as well as a way to learn more about
|
||||
improving code quality.
|
||||
|
||||
If you would like to know whether an idea would fit in the general strategy of
|
||||
the Emogrifier project or would like to get feedback on the best architecture
|
||||
for your ideas, we propose you open a ticket first and discuss your ideas there
|
||||
first before investing a lot of time in writing code.
|
||||
|
||||
|
||||
## Install the development dependencies
|
||||
|
||||
To install the development dependencies (PHPUnit and PHP_CodeSniffer), please
|
||||
run the following commands:
|
||||
|
||||
```shell
|
||||
composer install
|
||||
composer require --dev slevomat/coding-standard:^4.0
|
||||
```
|
||||
|
||||
Note that the development dependencies (in particular, for PHP_CodeSniffer)
|
||||
require PHP 7.0 or later. The second command installs the PHP_CodeSniffer
|
||||
dependencies and should be omitted if specifically testing against an earlier
|
||||
version of PHP, however you will not be able to run the static code analysis.
|
||||
|
||||
|
||||
## Unit-test your changes
|
||||
|
||||
Please cover all changes with unit tests and make sure that your code does not
|
||||
break any existing tests. We will only merge pull requests that include full
|
||||
code coverage of the fixed bugs and the new features.
|
||||
|
||||
To run the existing PHPUnit tests, run this command:
|
||||
|
||||
```shell
|
||||
composer ci:tests:unit
|
||||
```
|
||||
|
||||
|
||||
## Coding Style
|
||||
|
||||
Please use the same coding style (PSR-2) as the rest of the code. Indentation
|
||||
is four spaces.
|
||||
|
||||
We will only merge pull requests that follow the project's coding style.
|
||||
|
||||
Please check your code with the provided static code analysis tools:
|
||||
|
||||
```shell
|
||||
composer ci:static
|
||||
```
|
||||
|
||||
Please make your code clean, well-readable and easy to understand.
|
||||
|
||||
If you add new methods or fields, please add proper PHPDoc for the new
|
||||
methods/fields. Please use grammatically correct, complete sentences in the
|
||||
code documentation.
|
||||
|
||||
You can autoformat your code using the following command:
|
||||
|
||||
```shell
|
||||
composer php:fix
|
||||
```
|
||||
|
||||
|
||||
## Git commits
|
||||
|
||||
Commit message should have a <= 50 character summary, optionally followed by a
|
||||
blank line and a more in depth description of 79 characters per line.
|
||||
|
||||
Please use grammatically correct, complete sentences in the commit messages.
|
||||
|
||||
Also, please prefix the subject line of the commit message with either
|
||||
[FEATURE], [TASK], [BUGFIX] OR [CLEANUP]. This makes it faster to see what
|
||||
a commit is about.
|
||||
|
||||
|
||||
## Creating pull requests (PRs)
|
||||
|
||||
When you create a pull request, please
|
||||
[make your PR editable](https://github.com/blog/2247-improving-collaboration-with-forks).
|
||||
@@ -1,100 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pelago\Tests\Support\Traits;
|
||||
|
||||
/**
|
||||
* Provides assertion methods for use with CSS content where whitespace may vary.
|
||||
*
|
||||
* @author Jake Hotson <jake.github@qzdesign.co.uk>
|
||||
*/
|
||||
trait AssertCss
|
||||
{
|
||||
/**
|
||||
* Processing of @media rules may involve removal of some unnecessary whitespace from the CSS placed in the <style>
|
||||
* element added to the docuemnt, due to the way that certain parts are `trim`med. Notably, whitespace either side
|
||||
* of "{", "}" and "," or at the beginning of the CSS may be removed.
|
||||
*
|
||||
* This method helps takes care of that, by converting a search needle for an exact match into a regular expression
|
||||
* that allows for such whitespace removal, so that the tests themselves do not need to be written less humanly
|
||||
* readable and can use inputs containing extra whitespace.
|
||||
*
|
||||
* @param string $needle Needle that would be used with `assertContains` or `assertNotContains`.
|
||||
*
|
||||
* @return string Needle to use with `assertRegExp` or `assertNotRegExp` instead.
|
||||
*/
|
||||
private static function getCssNeedleRegExp($needle)
|
||||
{
|
||||
$needleMatcher = \preg_replace_callback(
|
||||
'/\\s*+([{},])\\s*+|(^\\s++)|(>)\\s*+|(?:(?!\\s*+[{},]|^\\s)[^>])++/',
|
||||
function (array $matches) {
|
||||
if (isset($matches[1]) && $matches[1] !== '') {
|
||||
// matched possibly some whitespace, followed by "{", "}" or ",", then possibly more whitespace
|
||||
return '\\s*+' . \preg_quote($matches[1], '/') . '\\s*+';
|
||||
}
|
||||
if (isset($matches[2]) && $matches[2] !== '') {
|
||||
// matched whitespace at start
|
||||
return '\\s*+';
|
||||
}
|
||||
if (isset($matches[3]) && $matches[3] !== '') {
|
||||
// matched ">" (e.g. end of <style> tag) followed by possibly some whitespace
|
||||
return \preg_quote($matches[3], '/') . '\\s*+';
|
||||
}
|
||||
// matched any other sequence which could not overlap with the above
|
||||
return \preg_quote($matches[0], '/');
|
||||
},
|
||||
$needle
|
||||
);
|
||||
return '/' . $needleMatcher . '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Like `assertContains` but allows for removal of some unnecessary whitespace from the CSS.
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*/
|
||||
private static function assertContainsCss($needle, $haystack)
|
||||
{
|
||||
static::assertRegExp(
|
||||
static::getCssNeedleRegExp($needle),
|
||||
$haystack,
|
||||
'Plain text needle: "' . $needle . '"'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like `assertNotContains` and also enforces the assertion with removal of some unnecessary whitespace from the
|
||||
* CSS.
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*/
|
||||
private static function assertNotContainsCss($needle, $haystack)
|
||||
{
|
||||
static::assertNotRegExp(
|
||||
static::getCssNeedleRegExp($needle),
|
||||
$haystack,
|
||||
'Plain text needle: "' . $needle . '"'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a string of CSS occurs exactly a certain number of times in the result, allowing for removal of some
|
||||
* unnecessary whitespace.
|
||||
*
|
||||
* @param int $expectedCount
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*/
|
||||
private static function assertContainsCssCount(
|
||||
$expectedCount,
|
||||
$needle,
|
||||
$haystack
|
||||
) {
|
||||
static::assertSame(
|
||||
$expectedCount,
|
||||
\preg_match_all(static::getCssNeedleRegExp($needle), $haystack),
|
||||
'Plain text needle: "' . $needle . "\"\nHaystack: \"" . $haystack . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,317 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pelago\Tests\Unit\Emogrifier;
|
||||
|
||||
use Pelago\Emogrifier\CssConcatenator;
|
||||
|
||||
/**
|
||||
* Test case.
|
||||
*
|
||||
* @author Jake Hotson <jake.github@qzdesign.co.uk>
|
||||
*/
|
||||
class CssConcatenatorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var CssConcatenator
|
||||
*/
|
||||
private $subject = null;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
$this->subject = new CssConcatenator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function getCssInitiallyReturnsEmptyString()
|
||||
{
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
static::assertSame('', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function appendSetsFirstRule()
|
||||
{
|
||||
$this->subject->append(['p'], 'color: green;');
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
static::assertSame('p{color: green;}', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function appendWithMediaQuerySetsFirstRuleInMediaRule()
|
||||
{
|
||||
$this->subject->append(['p'], 'color: green;', '@media screen');
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
static::assertSame('@media screen{p{color: green;}}', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function equivalentSelectorsDataProvider()
|
||||
{
|
||||
return [
|
||||
'one selector' => [['p'], ['p']],
|
||||
'two selectors' => [
|
||||
['p', 'ul'],
|
||||
['p', 'ul'],
|
||||
],
|
||||
'two selectors in different order' => [
|
||||
['p', 'ul'],
|
||||
['ul', 'p'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string[] $selectors1
|
||||
* @param string[] $selectors2
|
||||
*
|
||||
* @dataProvider equivalentSelectorsDataProvider
|
||||
*/
|
||||
public function appendCombinesRulesWithEquivalentSelectors(array $selectors1, array $selectors2)
|
||||
{
|
||||
$this->subject->append($selectors1, 'color: green;');
|
||||
$this->subject->append($selectors2, 'font-size: 16px;');
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
$expectedResult = \implode(',', $selectors1) . '{color: green;font-size: 16px;}';
|
||||
|
||||
static::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function appendInsertsSemicolonCombiningRulesWithoutTrailingSemicolon()
|
||||
{
|
||||
$this->subject->append(['p'], 'color: green');
|
||||
$this->subject->append(['p'], 'font-size: 16px');
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
static::assertSame('p{color: green;font-size: 16px}', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function differentSelectorsDataProvider()
|
||||
{
|
||||
return [
|
||||
'single selectors' => [
|
||||
['p'],
|
||||
['ul'],
|
||||
['p', 'ul'],
|
||||
],
|
||||
'single selector and an entirely different pair' => [
|
||||
['p'],
|
||||
['ul', 'ol'],
|
||||
['p', 'ul', 'ol'],
|
||||
],
|
||||
'single selector and a superset pair' => [
|
||||
['p'],
|
||||
['p', 'ul'],
|
||||
['p', 'ul'],
|
||||
],
|
||||
'pair of selectors and an entirely different single' => [
|
||||
['p', 'ul'],
|
||||
['ol'],
|
||||
['p', 'ul', 'ol'],
|
||||
],
|
||||
'pair of selectors and a subset single' => [
|
||||
['p', 'ul'],
|
||||
['ul'],
|
||||
['p', 'ul'],
|
||||
],
|
||||
'entirely different pairs of selectors' => [
|
||||
['p', 'ul'],
|
||||
['ol', 'h1'],
|
||||
['p', 'ul', 'ol', 'h1'],
|
||||
],
|
||||
'pairs of selectors with one common' => [
|
||||
['p', 'ul'],
|
||||
['ul', 'ol'],
|
||||
['p', 'ul', 'ol'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string[] $selectors1
|
||||
* @param string[] $selectors2
|
||||
* @param string[] $combinedSelectors
|
||||
*
|
||||
* @dataProvider differentSelectorsDataProvider
|
||||
*/
|
||||
public function appendCombinesSameRulesWithDifferentSelectors(
|
||||
array $selectors1,
|
||||
array $selectors2,
|
||||
array $combinedSelectors
|
||||
) {
|
||||
$this->subject->append($selectors1, 'color: green;');
|
||||
$this->subject->append($selectors2, 'color: green;');
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
$expectedResult = \implode(',', $combinedSelectors) . '{color: green;}';
|
||||
|
||||
static::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string[] $selectors1
|
||||
* @param string[] $selectors2
|
||||
*
|
||||
* @dataProvider differentSelectorsDataProvider
|
||||
*/
|
||||
public function appendNotCombinesDifferentRulesWithDifferentSelectors(array $selectors1, array $selectors2)
|
||||
{
|
||||
$this->subject->append($selectors1, 'color: green;');
|
||||
$this->subject->append($selectors2, 'font-size: 16px;');
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
$expectedResult = \implode(',', $selectors1) . '{color: green;}'
|
||||
. \implode(',', $selectors2) . '{font-size: 16px;}';
|
||||
|
||||
static::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function appendCombinesRulesForSameMediaQueryInMediaRule()
|
||||
{
|
||||
$this->subject->append(['p'], 'color: green;', '@media screen');
|
||||
$this->subject->append(['ul'], 'font-size: 16px;', '@media screen');
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
static::assertSame('@media screen{p{color: green;}ul{font-size: 16px;}}', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string[] $selectors1
|
||||
* @param string[] $selectors2
|
||||
*
|
||||
* @dataProvider equivalentSelectorsDataProvider
|
||||
*/
|
||||
public function appendCombinesRulesWithEquivalentSelectorsWithinMediaRule(array $selectors1, array $selectors2)
|
||||
{
|
||||
$this->subject->append($selectors1, 'color: green;', '@media screen');
|
||||
$this->subject->append($selectors2, 'font-size: 16px;', '@media screen');
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
$expectedResult = '@media screen{' . \implode(',', $selectors1) . '{color: green;font-size: 16px;}}';
|
||||
|
||||
static::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string[] $selectors1
|
||||
* @param string[] $selectors2
|
||||
* @param string[] $combinedSelectors
|
||||
*
|
||||
* @dataProvider differentSelectorsDataProvider
|
||||
*/
|
||||
public function appendCombinesSameRulesWithDifferentSelectorsWithinMediaRule(
|
||||
array $selectors1,
|
||||
array $selectors2,
|
||||
array $combinedSelectors
|
||||
) {
|
||||
$this->subject->append($selectors1, 'color: green;', '@media screen');
|
||||
$this->subject->append($selectors2, 'color: green;', '@media screen');
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
$expectedResult = '@media screen{' . \implode(',', $combinedSelectors) . '{color: green;}}';
|
||||
|
||||
static::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function appendNotCombinesRulesForDifferentMediaQueryInMediaRule()
|
||||
{
|
||||
$this->subject->append(['p'], 'color: green;', '@media screen');
|
||||
$this->subject->append(['p'], 'color: green;', '@media print');
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
static::assertSame('@media screen{p{color: green;}}@media print{p{color: green;}}', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[][]
|
||||
*/
|
||||
public function combinableRulesDataProvider()
|
||||
{
|
||||
return [
|
||||
'same selectors' => [['p'], 'color: green;', ['p'], 'font-size: 16px;', ''],
|
||||
'same declarations block' => [['p'], 'color: green;', ['ul'], 'color: green;', ''],
|
||||
'same media query' => [['p'], 'color: green;', ['ul'], 'font-size: 16px;', '@media screen'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param array $rule1Selectors
|
||||
* @param string $rule1DeclarationsBlock
|
||||
* @param array $rule2Selectors
|
||||
* @param string $rule2DeclarationsBlock
|
||||
* @param string $media
|
||||
*
|
||||
* @dataProvider combinableRulesDataProvider
|
||||
*/
|
||||
public function appendNotCombinesNonadjacentRules(
|
||||
array $rule1Selectors,
|
||||
$rule1DeclarationsBlock,
|
||||
array $rule2Selectors,
|
||||
$rule2DeclarationsBlock,
|
||||
$media
|
||||
) {
|
||||
$this->subject->append($rule1Selectors, $rule1DeclarationsBlock, $media);
|
||||
$this->subject->append(['.intervening'], '-intervening-property: 0;');
|
||||
$this->subject->append($rule2Selectors, $rule2DeclarationsBlock, $media);
|
||||
|
||||
$result = $this->subject->getCss();
|
||||
|
||||
$expectedRule1Css = \implode(',', $rule1Selectors) . '{' . $rule1DeclarationsBlock . '}';
|
||||
$expectedRule2Css = \implode(',', $rule2Selectors) . '{' . $rule2DeclarationsBlock . '}';
|
||||
if ($media !== '') {
|
||||
$expectedRule1Css = $media . '{' . $expectedRule1Css . '}';
|
||||
$expectedRule2Css = $media . '{' . $expectedRule2Css . '}';
|
||||
}
|
||||
$expectedResult = $expectedRule1Css . '.intervening{-intervening-property: 0;}' . $expectedRule2Css;
|
||||
|
||||
static::assertSame($expectedResult, $result);
|
||||
}
|
||||
}
|
||||
@@ -1,385 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pelago\Tests\Unit\Emogrifier\HtmlProcessor;
|
||||
|
||||
use Pelago\Emogrifier\HtmlProcessor\AbstractHtmlProcessor;
|
||||
use Pelago\Tests\Unit\Emogrifier\HtmlProcessor\Fixtures\TestingHtmlProcessor;
|
||||
|
||||
/**
|
||||
* Test case.
|
||||
*
|
||||
* @author Oliver Klee <github@oliverklee.de>
|
||||
*/
|
||||
class AbstractHtmlProcessorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function fixtureIsAbstractHtmlProcessor()
|
||||
{
|
||||
static::assertInstanceOf(AbstractHtmlProcessor::class, new TestingHtmlProcessor('<html></html>'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function reformatsHtml()
|
||||
{
|
||||
$rawHtml = '<!DOCTYPE HTML>' .
|
||||
'<html>' .
|
||||
'<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>' .
|
||||
'<body></body>' .
|
||||
'</html>';
|
||||
$formattedHtml = "<!DOCTYPE HTML>\n" .
|
||||
"<html>\n" .
|
||||
'<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>' . "\n" .
|
||||
"<body></body>\n" .
|
||||
"</html>\n";
|
||||
|
||||
$subject = new TestingHtmlProcessor($rawHtml);
|
||||
|
||||
static::assertSame($formattedHtml, $subject->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function nonHtmlDataProvider()
|
||||
{
|
||||
return [
|
||||
'empty string' => [''],
|
||||
'null' => [null],
|
||||
'integer' => [2],
|
||||
'float' => [3.14159],
|
||||
'object' => [new \stdClass()],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @expectedException \InvalidArgumentException
|
||||
*
|
||||
* @param mixed $html
|
||||
*
|
||||
* @dataProvider nonHtmlDataProvider
|
||||
*/
|
||||
public function constructorWithNoHtmlDataThrowsException($html)
|
||||
{
|
||||
new TestingHtmlProcessor($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function invalidHtmlDataProvider()
|
||||
{
|
||||
return [
|
||||
'broken nesting gets nested' => ['<b><i></b></i>', '<b><i></i></b>'],
|
||||
'partial opening tag gets closed' => ['<b', '<b></b>'],
|
||||
'only opening tag gets closed' => ['<b>', '<b></b>'],
|
||||
'only closing tag gets removed' => ['foo</b> bar', 'foo bar'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $input
|
||||
* @param string $expectedHtml
|
||||
*
|
||||
* @dataProvider invalidHtmlDataProvider
|
||||
*/
|
||||
public function renderRepairsBrokenHtml($input, $expectedHtml)
|
||||
{
|
||||
$subject = new TestingHtmlProcessor($input);
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains($expectedHtml, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function contentWithoutHtmlTagDataProvider()
|
||||
{
|
||||
return [
|
||||
'doctype only' => ['<!DOCTYPE html>'],
|
||||
'body content only' => ['<p>Hello</p>'],
|
||||
'HEAD element' => ['<head></head>'],
|
||||
'BODY element' => ['<body></body>'],
|
||||
'HEAD AND BODY element' => ['<head></head><body></body>'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $html
|
||||
*
|
||||
* @dataProvider contentWithoutHtmlTagDataProvider
|
||||
*/
|
||||
public function addsMissingHtmlTag($html)
|
||||
{
|
||||
$subject = new TestingHtmlProcessor($html);
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains('<html>', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function contentWithoutHeadTagDataProvider()
|
||||
{
|
||||
return [
|
||||
'doctype only' => ['<!DOCTYPE html>'],
|
||||
'body content only' => ['<p>Hello</p>'],
|
||||
'BODY element' => ['<body></body>'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $html
|
||||
*
|
||||
* @dataProvider contentWithoutHeadTagDataProvider
|
||||
*/
|
||||
public function addsMissingHeadTag($html)
|
||||
{
|
||||
$subject = new TestingHtmlProcessor($html);
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains('<head>', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function contentWithoutBodyTagDataProvider()
|
||||
{
|
||||
return [
|
||||
'doctype only' => ['<!DOCTYPE html>'],
|
||||
'HEAD element' => ['<head></head>'],
|
||||
'body content only' => ['<p>Hello</p>'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $html
|
||||
*
|
||||
* @dataProvider contentWithoutBodyTagDataProvider
|
||||
*/
|
||||
public function addsMissingBodyTag($html)
|
||||
{
|
||||
$subject = new TestingHtmlProcessor($html);
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains('<body>', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function putsMissingBodyElementAroundBodyContent()
|
||||
{
|
||||
$subject = new TestingHtmlProcessor('<p>Hello</p>');
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains('<body><p>Hello</p></body>', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function specialCharactersDataProvider()
|
||||
{
|
||||
return [
|
||||
'template markers with dollar signs & square brackets' => ['$[USER:NAME]$'],
|
||||
'UTF-8 umlauts' => ['Küss die Hand, schöne Frau.'],
|
||||
'HTML entities' => ['a & b > c'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $codeNotToBeChanged
|
||||
*
|
||||
* @dataProvider specialCharactersDataProvider
|
||||
*/
|
||||
public function keepsSpecialCharacters($codeNotToBeChanged)
|
||||
{
|
||||
$html = '<html><p>' . $codeNotToBeChanged . '</p></html>';
|
||||
$subject = new TestingHtmlProcessor($html);
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains($codeNotToBeChanged, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function addMissingHtml5DocumentType()
|
||||
{
|
||||
$subject = new TestingHtmlProcessor('<html></html>');
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains('<!DOCTYPE html>', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function documentTypeDataProvider()
|
||||
{
|
||||
return [
|
||||
'HTML5' => ['<!DOCTYPE html>'],
|
||||
'XHTML 1.0 strict' => [
|
||||
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' .
|
||||
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
|
||||
],
|
||||
'XHTML 1.0 transitional' => [
|
||||
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ' .
|
||||
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
|
||||
],
|
||||
'HTML 4 transitional' => [
|
||||
'<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ' .
|
||||
'"http://www.w3.org/TR/REC-html40/loose.dtd">',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $documentType
|
||||
*
|
||||
* @dataProvider documentTypeDataProvider
|
||||
*/
|
||||
public function keepsExistingDocumentType($documentType)
|
||||
{
|
||||
$html = $documentType . '<html></html>';
|
||||
$subject = new TestingHtmlProcessor($html);
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains($documentType, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function addsMissingContentTypeMetaTag()
|
||||
{
|
||||
$subject = new TestingHtmlProcessor('<p>Hello</p>');
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function notAddsSecondContentTypeMetaTag()
|
||||
{
|
||||
$html = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>';
|
||||
$subject = new TestingHtmlProcessor($html);
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
$numberOfContentTypeMetaTags = \substr_count($result, 'Content-Type');
|
||||
static::assertSame(1, $numberOfContentTypeMetaTags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $documentType
|
||||
*
|
||||
* @dataProvider documentTypeDataProvider
|
||||
*/
|
||||
public function convertsXmlSelfClosingTagsToNonXmlSelfClosingTag($documentType)
|
||||
{
|
||||
$subject = new TestingHtmlProcessor($documentType . '<html><body><br/></body></html>');
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains('<body><br></body>', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $documentType
|
||||
*
|
||||
* @dataProvider documentTypeDataProvider
|
||||
*/
|
||||
public function keepsNonXmlSelfClosingTags($documentType)
|
||||
{
|
||||
$subject = new TestingHtmlProcessor($documentType . '<html><body><br></body></html>');
|
||||
|
||||
$result = $subject->render();
|
||||
|
||||
static::assertContains('<body><br></body>', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function renderBodyContentForEmptyBodyReturnsEmptyString()
|
||||
{
|
||||
$subject = new TestingHtmlProcessor('<html><body></body></html>');
|
||||
|
||||
$result = $subject->renderBodyContent();
|
||||
|
||||
static::assertSame('', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function renderBodyContentReturnsBodyContent()
|
||||
{
|
||||
$bodyContent = '<p>Hello world</p>';
|
||||
$subject = new TestingHtmlProcessor('<html><body>' . $bodyContent . '</body></html>');
|
||||
|
||||
$result = $subject->renderBodyContent();
|
||||
|
||||
static::assertSame($bodyContent, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function getDomDocumentReturnsDomDocument()
|
||||
{
|
||||
$subject = new TestingHtmlProcessor('<html></html>');
|
||||
|
||||
static::assertInstanceOf(\DOMDocument::class, $subject->getDomDocument());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function getDomDocumentWithNormalizedHtmlRepresentsTheGivenHtml()
|
||||
{
|
||||
$html = "<!DOCTYPE html>\n<html>\n<head>" .
|
||||
'<meta http-equiv="Content-Type" content="text/html; charset=utf-8">' .
|
||||
"</head>\n<body>\n<br>\n</body>\n</html>\n";
|
||||
$subject = new TestingHtmlProcessor($html);
|
||||
|
||||
$domDocument = $subject->getDomDocument();
|
||||
|
||||
self::assertSame($html, $domDocument->saveHTML());
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pelago\Tests\Unit\Emogrifier\HtmlProcessor;
|
||||
|
||||
use Pelago\Emogrifier\HtmlProcessor\AbstractHtmlProcessor;
|
||||
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
|
||||
|
||||
/**
|
||||
* Test case.
|
||||
*
|
||||
* @author Oliver Klee <github@oliverklee.de>
|
||||
*/
|
||||
class CssToAttributeConverterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function classIsAbstractHtmlProcessor()
|
||||
{
|
||||
static::assertInstanceOf(AbstractHtmlProcessor::class, new CssToAttributeConverter('<html></html>'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function renderWithoutConvertCssToVisualAttributesCallNotAddsVisuablAttributes()
|
||||
{
|
||||
$html = '<html style="text-align: right;"></html>';
|
||||
$subject = new CssToAttributeConverter($html);
|
||||
|
||||
static::assertContains('<html style="text-align: right;">', $subject->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function convertCssToVisualAttributesUsesFluentInterface()
|
||||
{
|
||||
$html = '<html style="text-align: right;"></html>';
|
||||
$subject = new CssToAttributeConverter($html);
|
||||
|
||||
static::assertSame($subject, $subject->convertCssToVisualAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function matchingCssToHtmlMappingDataProvider()
|
||||
{
|
||||
return [
|
||||
'background-color => bgcolor' => ['<p style="background-color: red;">hi</p>', 'bgcolor="red"'],
|
||||
'background-color with !important => bgcolor' => [
|
||||
'<p style="background-color: red !important;">hi</p>',
|
||||
'bgcolor="red"',
|
||||
],
|
||||
'p.text-align => align' => ['<p style="text-align: left;">hi</p>', 'align="left"'],
|
||||
'div.text-align => align' => ['<div style="text-align: left;">hi</div>', 'align="left"'],
|
||||
'td.text-align => align' => [
|
||||
'<table><tr><td style="text-align: left;">hi</td></tr></table>',
|
||||
'align="left',
|
||||
],
|
||||
'text-align: left => align=left' => ['<p style="text-align: left;">hi</p>', 'align="left"'],
|
||||
'text-align: right => align=right' => ['<p style="text-align: right;">hi</p>', 'align="right"'],
|
||||
'text-align: center => align=center' => ['<p style="text-align: center;">hi</p>', 'align="center"'],
|
||||
'text-align: justify => align:justify' => ['<p style="text-align: justify;">hi</p>', 'align="justify"'],
|
||||
'img.float: right => align=right' => ['<img style="float: right;">', 'align="right"'],
|
||||
'img.float: left => align=left' => ['<img style="float: left;">', 'align="left"'],
|
||||
'table.float: right => align=right' => ['<table style="float: right;"></table>', 'align="right"'],
|
||||
'table.float: left => align=left' => ['<table style="float: left;"></table>', 'align="left"'],
|
||||
'table.border-spacing: 0 => cellspacing=0' => [
|
||||
'<table style="border-spacing: 0;"></table>',
|
||||
'cellspacing="0"',
|
||||
],
|
||||
'background => bgcolor' => ['<p style="background: red top;">Bonjour</p>', 'bgcolor="red"'],
|
||||
'width with px' => ['<p style="width: 100px;">Hi</p>', 'width="100"'],
|
||||
'width with %' => ['<p style="width: 50%;">Hi</p>', 'width="50%"'],
|
||||
'height with px' => ['<p style="height: 100px;">Hi</p>', 'height="100"'],
|
||||
'height with %' => ['<p style="height: 50%;">Hi</p>', 'height="50%"'],
|
||||
'img.margin: 0 auto (horizontal centering) => align=center' => [
|
||||
'<img style="margin: 0 auto;">',
|
||||
'align="center"',
|
||||
],
|
||||
'img.margin: auto (horizontal centering) => align=center' => [
|
||||
'<img style="margin: auto;">',
|
||||
'align="center"',
|
||||
],
|
||||
'img.margin: 10 auto 30 auto (horizontal centering) => align=center' => [
|
||||
'<img style="margin: 10 auto 30 auto;">',
|
||||
'align="center"',
|
||||
],
|
||||
'table.margin: 0 auto (horizontal centering) => align=center' => [
|
||||
'<table style="margin: 0 auto;"></table>',
|
||||
'align="center"',
|
||||
],
|
||||
'table.margin: auto (horizontal centering) => align=center' => [
|
||||
'<table style="margin: auto;"></table>',
|
||||
'align="center"',
|
||||
],
|
||||
'table.margin: 10 auto 30 auto (horizontal centering) => align=center' => [
|
||||
'<table style="margin: 10 auto 30 auto;"></table>',
|
||||
'align="center"',
|
||||
],
|
||||
'img.border: none => border=0' => ['<img style="border: none;">', 'border="0"'],
|
||||
'img.border: 0 => border=0' => ['<img style="border: none;">', 'border="0"'],
|
||||
'table.border: none => border=0' => ['<table style="border: none;"></table>', 'border="0"'],
|
||||
'table.border: 0 => border=0' => ['<table style="border: 0;"></table>', 'border="0"'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $body The HTML
|
||||
* @param string $attributes The attributes that are expected on the element
|
||||
*
|
||||
* @dataProvider matchingCssToHtmlMappingDataProvider
|
||||
*/
|
||||
public function convertCssToVisualAttributesMapsSuitableCssToHtml($body, $attributes)
|
||||
{
|
||||
$subject = new CssToAttributeConverter('<html><body>' . $body . '</body></html>');
|
||||
|
||||
$subject->convertCssToVisualAttributes();
|
||||
$html = $subject->render();
|
||||
|
||||
static::assertContains($attributes, $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function notMatchingCssToHtmlMappingDataProvider()
|
||||
{
|
||||
return [
|
||||
'background URL' => ['<p style="background: url(bg.png);">Hello</p>'],
|
||||
'background URL with position' => ['<p style="background: url(bg.png) top;">Hello</p>'],
|
||||
'p.margin: 10 5 30 auto (no horizontal centering)' => ['<img style="margin: 10 5 30 auto;">'],
|
||||
'p.margin: auto' => ['<p style="margin: auto;">Hi</p>'],
|
||||
'p.border: none' => ['<p style="border: none;">Hi</p>'],
|
||||
'img.border: 1px solid black' => ['<img style="border: 1px solid black;">'],
|
||||
'span.text-align' => ['<span style="text-align: justify;">Hi</span>'],
|
||||
'text-align: inherit' => ['<p style="text-align: inherit;">Hi</p>'],
|
||||
'span.float' => ['<span style="float: right;">Hi</span>'],
|
||||
'float: none' => ['<table style="float: none;"></table>'],
|
||||
'p.border-spacing' => ['<p style="border-spacing: 5px;">Hi</p>'],
|
||||
'height: auto' => ['<img src="logo.png" alt="" style="height: auto;">'],
|
||||
'width: auto' => ['<img src="logo.png" alt="" style="width: auto;">'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $body the HTML
|
||||
*
|
||||
* @dataProvider notMatchingCssToHtmlMappingDataProvider
|
||||
*/
|
||||
public function convertCssToVisualAttributesNotMapsUnsuitableCssToHtml($body)
|
||||
{
|
||||
$subject = new CssToAttributeConverter('<html><body>' . $body . '</body></html>');
|
||||
|
||||
$subject->convertCssToVisualAttributes();
|
||||
$html = $subject->render();
|
||||
|
||||
static::assertContains($body, $html);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pelago\Tests\Unit\Emogrifier\HtmlProcessor\Fixtures;
|
||||
|
||||
use Pelago\Emogrifier\HtmlProcessor\AbstractHtmlProcessor;
|
||||
|
||||
/**
|
||||
* Fixture class for AbstractHtmlProcessor.
|
||||
*
|
||||
* @author Oliver Klee <github@oliverklee.de>
|
||||
*/
|
||||
class TestingHtmlProcessor extends AbstractHtmlProcessor
|
||||
{
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pelago\Tests\Unit\Emogrifier\HtmlProcessor;
|
||||
|
||||
use Pelago\Emogrifier\HtmlProcessor\AbstractHtmlProcessor;
|
||||
use Pelago\Emogrifier\HtmlProcessor\HtmlNormalizer;
|
||||
|
||||
/**
|
||||
* Test case.
|
||||
*
|
||||
* @author Oliver Klee <github@oliverklee.de>
|
||||
*/
|
||||
class HtmlNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function classIsAbstractHtmlProcessor()
|
||||
{
|
||||
static::assertInstanceOf(AbstractHtmlProcessor::class, new HtmlNormalizer('<html></html>'));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,333 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pelago\Tests\Unit\Support\Traits;
|
||||
|
||||
use Pelago\Tests\Support\Traits\AssertCss;
|
||||
|
||||
/**
|
||||
* Test case.
|
||||
*
|
||||
* @author Jake Hotson <jake.github@qzdesign.co.uk>
|
||||
*/
|
||||
class AssertCssTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
use AssertCss;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function getCssNeedleRegExpEscapesAllSpecialCharacters()
|
||||
{
|
||||
$needle = '.\\+*?[^]$(){}=!<>|:-/';
|
||||
|
||||
$result = static::getCssNeedleRegExp($needle);
|
||||
|
||||
$resultWithWhitespaceMatchersRemoved = \str_replace('\\s*+', '', $result);
|
||||
|
||||
static::assertSame(
|
||||
'/' . \preg_quote($needle, '/') . '/',
|
||||
$resultWithWhitespaceMatchersRemoved
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function getCssNeedleRegExpNotEscapesNonSpecialCharacters()
|
||||
{
|
||||
$needle = \implode('', \array_merge(\range('a', 'z'), \range('A', 'Z'), \range('0 ', '9 ')))
|
||||
. "\r\n\t `¬\"£%&_;'@~,";
|
||||
|
||||
$result = static::getCssNeedleRegExp($needle);
|
||||
|
||||
$resultWithWhitespaceMatchersRemoved = \str_replace('\\s*+', '', $result);
|
||||
|
||||
static::assertSame(
|
||||
'/' . $needle . '/',
|
||||
$resultWithWhitespaceMatchersRemoved
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function contentWithOptionalWhitespaceDataProvider()
|
||||
{
|
||||
return [
|
||||
'"{" alone' => ['{', ''],
|
||||
'"}" alone' => ['}', ''],
|
||||
'"," alone' => [',', ''],
|
||||
'"{" with non-special character' => ['{', 'a'],
|
||||
'"{" with two non-special characters' => ['{', 'a0'],
|
||||
'"{" with special character' => ['{', '.'],
|
||||
'"{" with two special characters' => ['{', '.+'],
|
||||
'"{" with special character and non-special character' => ['{', '.a'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $contentToInsertAround
|
||||
* @param string $otherContent
|
||||
*
|
||||
* @dataProvider contentWithOptionalWhitespaceDataProvider
|
||||
*/
|
||||
public function getCssNeedleRegExpInsertsOptionalWhitespace($contentToInsertAround, $otherContent)
|
||||
{
|
||||
$result = static::getCssNeedleRegExp($otherContent . $contentToInsertAround . $otherContent);
|
||||
|
||||
$quotedOtherContent = \preg_quote($otherContent, '/');
|
||||
$expectedResult = '/' . $quotedOtherContent . '\\s*+' . \preg_quote($contentToInsertAround, '/') . '\\s*+'
|
||||
. $quotedOtherContent . '/';
|
||||
|
||||
static::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function getCssNeedleRegExpReplacesWhitespaceAtStartWithOptionalWhitespace()
|
||||
{
|
||||
$result = static::getCssNeedleRegExp(' a');
|
||||
|
||||
static::assertSame('/\\s*+a/', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function styleTagDataProvider()
|
||||
{
|
||||
return [
|
||||
'without space after' => ['<style>a'],
|
||||
'one space after' => ['<style> a'],
|
||||
'two spaces after' => ['<style> a'],
|
||||
'linefeed after' => ["<style>\na"],
|
||||
'Windows line ending after' => ["<style>\r\na"],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
*
|
||||
* @dataProvider styleTagDataProvider
|
||||
*/
|
||||
public function getCssNeedleRegExpInsertsOptionalWhitespaceAfterStyleTag($needle)
|
||||
{
|
||||
$result = static::getCssNeedleRegExp($needle);
|
||||
|
||||
static::assertSame('/\\<style\\>\\s*+a/', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function needleFoundDataProvider()
|
||||
{
|
||||
$cssStrings = [
|
||||
'unminified CSS' => 'html, body { color: green; }',
|
||||
'minified CSS' => 'html,body{color: green;}',
|
||||
'CSS with extra spaces' => ' html , body { color: green; }',
|
||||
'CSS with linefeeds' => "\nhtml\n,\nbody\n{\ncolor: green;\n}",
|
||||
'CSS with Windows line endings' => "\r\nhtml\r\n,\r\nbody\r\n{\r\ncolor: green;\r\n}",
|
||||
];
|
||||
|
||||
$datasets = [];
|
||||
foreach ($cssStrings as $needleDescription => $needle) {
|
||||
foreach ($cssStrings as $haystackDescription => $haystack) {
|
||||
$description = $needleDescription . ' in ' . $haystackDescription;
|
||||
$datasets[$description] = [$needle, $haystack];
|
||||
$datasets[$description . ' in <style> tag'] = [
|
||||
'<style>' . $needle . '</style>',
|
||||
'<style>' . $haystack . '</style>',
|
||||
];
|
||||
}
|
||||
}
|
||||
return $datasets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function needleNotFoundDataProvider()
|
||||
{
|
||||
return [
|
||||
'CSS part with "{" not in CSS' => ['p {', 'body { color: green; }'],
|
||||
'CSS part with "}" not in CSS' => ['color: red; }', 'body { color: green; }'],
|
||||
'CSS part with "," not in CSS' => ['html, body', 'body { color: green; }'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleFoundDataProvider
|
||||
*/
|
||||
public function assertContainsCssPassesTestIfNeedleFound($needle, $haystack)
|
||||
{
|
||||
static::assertContainsCss($needle, $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleNotFoundDataProvider
|
||||
*
|
||||
* @expectedException \PHPUnit_Framework_ExpectationFailedException
|
||||
*/
|
||||
public function assertContainsCssFailsTestIfNeedleNotFound($needle, $haystack)
|
||||
{
|
||||
static::assertContainsCss($needle, $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleNotFoundDataProvider
|
||||
*/
|
||||
public function assertNotContainsCssPassesTestIfNeedleNotFound($needle, $haystack)
|
||||
{
|
||||
static::assertNotContainsCss($needle, $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleFoundDataProvider
|
||||
*
|
||||
* @expectedException \PHPUnit_Framework_ExpectationFailedException
|
||||
*/
|
||||
public function assertNotContainsCssFailsTestIfNeedleFound($needle, $haystack)
|
||||
{
|
||||
static::assertNotContainsCss($needle, $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleNotFoundDataProvider
|
||||
*/
|
||||
public function assertContainsCssCountPassesTestExpectingZeroIfNeedleNotFound($needle, $haystack)
|
||||
{
|
||||
static::assertContainsCssCount(0, $needle, $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleFoundDataProvider
|
||||
*
|
||||
* @expectedException \PHPUnit_Framework_ExpectationFailedException
|
||||
*/
|
||||
public function assertContainsCssCountFailsTestExpectingZeroIfNeedleFound($needle, $haystack)
|
||||
{
|
||||
static::assertContainsCssCount(0, $needle, $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleFoundDataProvider
|
||||
*/
|
||||
public function assertContainsCssCountPassesTestExpectingOneIfNeedleFound($needle, $haystack)
|
||||
{
|
||||
static::assertContainsCssCount(1, $needle, $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleNotFoundDataProvider
|
||||
*
|
||||
* @expectedException \PHPUnit_Framework_ExpectationFailedException
|
||||
*/
|
||||
public function assertContainsCssCountFailsTestExpectingOneIfNeedleNotFound($needle, $haystack)
|
||||
{
|
||||
static::assertContainsCssCount(1, $needle, $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleFoundDataProvider
|
||||
*
|
||||
* @expectedException \PHPUnit_Framework_ExpectationFailedException
|
||||
*/
|
||||
public function assertContainsCssCountFailsTestExpectingOneIfNeedleFoundTwice($needle, $haystack)
|
||||
{
|
||||
static::assertContainsCssCount(1, $needle, $haystack . $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleFoundDataProvider
|
||||
*/
|
||||
public function assertContainsCssCountPassesTestExpectingTwoIfNeedleFoundTwice($needle, $haystack)
|
||||
{
|
||||
static::assertContainsCssCount(2, $needle, $haystack . $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleNotFoundDataProvider
|
||||
*
|
||||
* @expectedException \PHPUnit_Framework_ExpectationFailedException
|
||||
*/
|
||||
public function assertContainsCssCountFailsTestExpectingTwoIfNeedleNotFound($needle, $haystack)
|
||||
{
|
||||
static::assertContainsCssCount(2, $needle, $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*
|
||||
* @dataProvider needleFoundDataProvider
|
||||
*
|
||||
* @expectedException \PHPUnit_Framework_ExpectationFailedException
|
||||
*/
|
||||
public function assertContainsCssCountFailsTestExpectingTwoIfNeedleFoundOnlyOnce($needle, $haystack)
|
||||
{
|
||||
static::assertContainsCssCount(2, $needle, $haystack);
|
||||
}
|
||||
}
|
||||
@@ -1,515 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* SCSSPHP
|
||||
*
|
||||
* @copyright 2012-2019 Leaf Corcoran
|
||||
*
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
* @link http://scssphp.github.io/scssphp
|
||||
*/
|
||||
|
||||
namespace ScssPhp\ScssPhp;
|
||||
|
||||
use ScssPhp\ScssPhp\Compiler;
|
||||
use ScssPhp\ScssPhp\Exception\ServerException;
|
||||
use ScssPhp\ScssPhp\Version;
|
||||
|
||||
/**
|
||||
* Server
|
||||
*
|
||||
* @author Leaf Corcoran <leafot@gmail.com>
|
||||
*/
|
||||
class Server
|
||||
{
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $showErrorsAsCSS;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dir;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $cacheDir;
|
||||
|
||||
/**
|
||||
* @var \ScssPhp\ScssPhp\Compiler
|
||||
*/
|
||||
private $scss;
|
||||
|
||||
/**
|
||||
* Join path components
|
||||
*
|
||||
* @param string $left Path component, left of the directory separator
|
||||
* @param string $right Path component, right of the directory separator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function join($left, $right)
|
||||
{
|
||||
return rtrim($left, '/\\') . DIRECTORY_SEPARATOR . ltrim($right, '/\\');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name of requested .scss file
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function inputName()
|
||||
{
|
||||
switch (true) {
|
||||
case isset($_GET['p']):
|
||||
return $_GET['p'];
|
||||
case isset($_SERVER['PATH_INFO']):
|
||||
return $_SERVER['PATH_INFO'];
|
||||
case isset($_SERVER['DOCUMENT_URI']):
|
||||
return substr($_SERVER['DOCUMENT_URI'], strlen($_SERVER['SCRIPT_NAME']));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to requested .scss file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function findInput()
|
||||
{
|
||||
if (($input = $this->inputName())
|
||||
&& strpos($input, '..') === false
|
||||
&& substr($input, -5) === '.scss'
|
||||
) {
|
||||
$name = $this->join($this->dir, $input);
|
||||
|
||||
if (is_file($name) && is_readable($name)) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to cached .css file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function cacheName($fname)
|
||||
{
|
||||
return $this->join($this->cacheDir, md5($fname) . '.css');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to meta data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function metadataName($out)
|
||||
{
|
||||
return $out . '.meta';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether .scss file needs to be re-compiled.
|
||||
*
|
||||
* @param string $out Output path
|
||||
* @param string $etag ETag
|
||||
*
|
||||
* @return boolean True if compile required.
|
||||
*/
|
||||
protected function needsCompile($out, &$etag)
|
||||
{
|
||||
if (! is_file($out)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$mtime = filemtime($out);
|
||||
|
||||
$metadataName = $this->metadataName($out);
|
||||
|
||||
if (is_readable($metadataName)) {
|
||||
$metadata = unserialize(file_get_contents($metadataName));
|
||||
|
||||
foreach ($metadata['imports'] as $import => $originalMtime) {
|
||||
$currentMtime = filemtime($import);
|
||||
|
||||
if ($currentMtime !== $originalMtime || $currentMtime > $mtime) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$metaVars = crc32(serialize($this->scss->getVariables()));
|
||||
|
||||
if ($metaVars !== $metadata['vars']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$etag = $metadata['etag'];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get If-Modified-Since header from client request
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getIfModifiedSinceHeader()
|
||||
{
|
||||
$modifiedSince = null;
|
||||
|
||||
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
||||
$modifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
|
||||
|
||||
if (false !== ($semicolonPos = strpos($modifiedSince, ';'))) {
|
||||
$modifiedSince = substr($modifiedSince, 0, $semicolonPos);
|
||||
}
|
||||
}
|
||||
|
||||
return $modifiedSince;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get If-None-Match header from client request
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getIfNoneMatchHeader()
|
||||
{
|
||||
$noneMatch = null;
|
||||
|
||||
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
|
||||
$noneMatch = $_SERVER['HTTP_IF_NONE_MATCH'];
|
||||
}
|
||||
|
||||
return $noneMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile .scss file
|
||||
*
|
||||
* @param string $in Input path (.scss)
|
||||
* @param string $out Output path (.css)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function compile($in, $out)
|
||||
{
|
||||
$start = microtime(true);
|
||||
$css = $this->scss->compile(file_get_contents($in), $in);
|
||||
$elapsed = round((microtime(true) - $start), 4);
|
||||
|
||||
$v = Version::VERSION;
|
||||
$t = gmdate('r');
|
||||
$css = "/* compiled by scssphp $v on $t (${elapsed}s) */\n\n" . $css;
|
||||
$etag = md5($css);
|
||||
|
||||
file_put_contents($out, $css);
|
||||
file_put_contents(
|
||||
$this->metadataName($out),
|
||||
serialize([
|
||||
'etag' => $etag,
|
||||
'imports' => $this->scss->getParsedFiles(),
|
||||
'vars' => crc32(serialize($this->scss->getVariables())),
|
||||
])
|
||||
);
|
||||
|
||||
return [$css, $etag];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format error as a pseudo-element in CSS
|
||||
*
|
||||
* @param \Exception $error
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createErrorCSS(\Exception $error)
|
||||
{
|
||||
$message = str_replace(
|
||||
["'", "\n"],
|
||||
["\\'", "\\A"],
|
||||
$error->getfile() . ":\n\n" . $error->getMessage()
|
||||
);
|
||||
|
||||
return "body { display: none !important; }
|
||||
html:after {
|
||||
background: white;
|
||||
color: black;
|
||||
content: '$message';
|
||||
display: block !important;
|
||||
font-family: mono;
|
||||
padding: 1em;
|
||||
white-space: pre;
|
||||
}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Render errors as a pseudo-element within valid CSS, displaying the errors on any
|
||||
* page that includes this CSS.
|
||||
*
|
||||
* @param boolean $show
|
||||
*/
|
||||
public function showErrorsAsCSS($show = true)
|
||||
{
|
||||
$this->showErrorsAsCSS = $show;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile .scss file
|
||||
*
|
||||
* @param string $in Input file (.scss)
|
||||
* @param string $out Output file (.css) optional
|
||||
*
|
||||
* @return string|bool
|
||||
*
|
||||
* @throws \ScssPhp\ScssPhp\Exception\ServerException
|
||||
*/
|
||||
public function compileFile($in, $out = null)
|
||||
{
|
||||
if (! is_readable($in)) {
|
||||
throw new ServerException('load error: failed to find ' . $in);
|
||||
}
|
||||
|
||||
$pi = pathinfo($in);
|
||||
|
||||
$this->scss->addImportPath($pi['dirname'] . '/');
|
||||
|
||||
$compiled = $this->scss->compile(file_get_contents($in), $in);
|
||||
|
||||
if ($out !== null) {
|
||||
return file_put_contents($out, $compiled);
|
||||
}
|
||||
|
||||
return $compiled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if file need compiling
|
||||
*
|
||||
* @param string $in Input file (.scss)
|
||||
* @param string $out Output file (.css)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function checkedCompile($in, $out)
|
||||
{
|
||||
if (! is_file($out) || filemtime($in) > filemtime($out)) {
|
||||
$this->compileFile($in, $out);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile requested scss and serve css. Outputs HTTP response.
|
||||
*
|
||||
* @param string $salt Prefix a string to the filename for creating the cache name hash
|
||||
*/
|
||||
public function serve($salt = '')
|
||||
{
|
||||
$protocol = isset($_SERVER['SERVER_PROTOCOL'])
|
||||
? $_SERVER['SERVER_PROTOCOL']
|
||||
: 'HTTP/1.0';
|
||||
|
||||
if ($input = $this->findInput()) {
|
||||
$output = $this->cacheName($salt . $input);
|
||||
$etag = $noneMatch = trim($this->getIfNoneMatchHeader(), '"');
|
||||
|
||||
if ($this->needsCompile($output, $etag)) {
|
||||
try {
|
||||
list($css, $etag) = $this->compile($input, $output);
|
||||
|
||||
$lastModified = gmdate('r', filemtime($output));
|
||||
|
||||
header('Last-Modified: ' . $lastModified);
|
||||
header('Content-type: text/css');
|
||||
header('ETag: "' . $etag . '"');
|
||||
|
||||
echo $css;
|
||||
} catch (\Exception $e) {
|
||||
if ($this->showErrorsAsCSS) {
|
||||
header('Content-type: text/css');
|
||||
|
||||
echo $this->createErrorCSS($e);
|
||||
} else {
|
||||
header($protocol . ' 500 Internal Server Error');
|
||||
header('Content-type: text/plain');
|
||||
|
||||
echo 'Parse error: ' . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
header('X-SCSS-Cache: true');
|
||||
header('Content-type: text/css');
|
||||
header('ETag: "' . $etag . '"');
|
||||
|
||||
if ($etag === $noneMatch) {
|
||||
header($protocol . ' 304 Not Modified');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$modifiedSince = $this->getIfModifiedSinceHeader();
|
||||
$mtime = filemtime($output);
|
||||
|
||||
if (strtotime($modifiedSince) === $mtime) {
|
||||
header($protocol . ' 304 Not Modified');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$lastModified = gmdate('r', $mtime);
|
||||
header('Last-Modified: ' . $lastModified);
|
||||
|
||||
echo file_get_contents($output);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
header($protocol . ' 404 Not Found');
|
||||
header('Content-type: text/plain');
|
||||
|
||||
$v = Version::VERSION;
|
||||
echo "/* INPUT NOT FOUND scss $v */\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on explicit input/output files does a full change check on cache before compiling.
|
||||
*
|
||||
* @param string $in
|
||||
* @param string $out
|
||||
* @param boolean $force
|
||||
*
|
||||
* @return string Compiled CSS results
|
||||
*
|
||||
* @throws \ScssPhp\ScssPhp\Exception\ServerException
|
||||
*/
|
||||
public function checkedCachedCompile($in, $out, $force = false)
|
||||
{
|
||||
if (! is_file($in) || ! is_readable($in)) {
|
||||
throw new ServerException('Invalid or unreadable input file specified.');
|
||||
}
|
||||
|
||||
if (is_dir($out) || ! is_writable(file_exists($out) ? $out : dirname($out))) {
|
||||
throw new ServerException('Invalid or unwritable output file specified.');
|
||||
}
|
||||
|
||||
if ($force || $this->needsCompile($out, $etag)) {
|
||||
list($css, $etag) = $this->compile($in, $out);
|
||||
} else {
|
||||
$css = file_get_contents($out);
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute scssphp on a .scss file or a scssphp cache structure
|
||||
*
|
||||
* The scssphp cache structure contains information about a specific
|
||||
* scss file having been parsed. It can be used as a hint for future
|
||||
* calls to determine whether or not a rebuild is required.
|
||||
*
|
||||
* The cache structure contains two important keys that may be used
|
||||
* externally:
|
||||
*
|
||||
* compiled: The final compiled CSS
|
||||
* updated: The time (in seconds) the CSS was last compiled
|
||||
*
|
||||
* The cache structure is a plain-ol' PHP associative array and can
|
||||
* be serialized and unserialized without a hitch.
|
||||
*
|
||||
* @param mixed $in Input
|
||||
* @param boolean $force Force rebuild?
|
||||
*
|
||||
* @return array scssphp cache structure
|
||||
*/
|
||||
public function cachedCompile($in, $force = false)
|
||||
{
|
||||
// assume no root
|
||||
$root = null;
|
||||
|
||||
if (is_string($in)) {
|
||||
$root = $in;
|
||||
} elseif (is_array($in) and isset($in['root'])) {
|
||||
if ($force or ! isset($in['files'])) {
|
||||
// If we are forcing a recompile or if for some reason the
|
||||
// structure does not contain any file information we should
|
||||
// specify the root to trigger a rebuild.
|
||||
$root = $in['root'];
|
||||
} elseif (isset($in['files']) and is_array($in['files'])) {
|
||||
foreach ($in['files'] as $fname => $ftime) {
|
||||
if (! file_exists($fname) or filemtime($fname) > $ftime) {
|
||||
// One of the files we knew about previously has changed
|
||||
// so we should look at our incoming root again.
|
||||
$root = $in['root'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: Throw an exception? We got neither a string nor something
|
||||
// that looks like a compatible lessphp cache structure.
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($root !== null) {
|
||||
// If we have a root value which means we should rebuild.
|
||||
$out = [];
|
||||
$out['root'] = $root;
|
||||
$out['compiled'] = $this->compileFile($root);
|
||||
$out['files'] = $this->scss->getParsedFiles();
|
||||
$out['updated'] = time();
|
||||
return $out;
|
||||
} else {
|
||||
// No changes, pass back the structure
|
||||
// we were given initially.
|
||||
return $in;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $dir Root directory to .scss files
|
||||
* @param string $cacheDir Cache directory
|
||||
* @param \ScssPhp\ScssPhp\Compiler|null $scss SCSS compiler instance
|
||||
*/
|
||||
public function __construct($dir, $cacheDir = null, $scss = null)
|
||||
{
|
||||
$this->dir = $dir;
|
||||
|
||||
if (! isset($cacheDir)) {
|
||||
$cacheDir = $this->join($dir, 'scss_cache');
|
||||
}
|
||||
|
||||
$this->cacheDir = $cacheDir;
|
||||
|
||||
if (! is_dir($this->cacheDir)) {
|
||||
throw new ServerException('Cache directory doesn\'t exist: ' . $cacheDir);
|
||||
}
|
||||
|
||||
if (! isset($scss)) {
|
||||
$scss = new Compiler();
|
||||
$scss->setImportPaths($this->dir);
|
||||
}
|
||||
|
||||
$this->scss = $scss;
|
||||
$this->showErrorsAsCSS = false;
|
||||
|
||||
date_default_timezone_set('UTC');
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<!-- Please fill in this template according to your issue. -->
|
||||
|
||||
| Q | A
|
||||
| ------------------- | -----
|
||||
| Bug report? | yes/no
|
||||
| Feature request? | yes/no
|
||||
| RFC? | yes/no
|
||||
| How used? | Standalone/Symfony/3party
|
||||
| Swiftmailer version | x.y.z
|
||||
| PHP version | x.y.z
|
||||
|
||||
### Observed behaviour
|
||||
<!-- What does the code do? -->
|
||||
|
||||
### Expected behaviour
|
||||
<!-- What should the code do? -->
|
||||
|
||||
### Example
|
||||
<!-- Example to reproduce the issue. -->
|
||||
@@ -1,14 +0,0 @@
|
||||
<!-- Please fill in this template according to the PR you're about to submit. -->
|
||||
|
||||
| Q | A
|
||||
| ------------- | ---
|
||||
| Bug fix? | yes/no
|
||||
| New feature? | yes/no
|
||||
| Doc update? | yes/no
|
||||
| BC breaks? | yes/no
|
||||
| Deprecations? | yes/no
|
||||
| Fixed tickets | #... <!-- #-prefixed issue number(s), if any -->
|
||||
| License | MIT
|
||||
|
||||
|
||||
<!-- Replace this comment by the description of your issue. -->
|
||||
@@ -1,739 +0,0 @@
|
||||
Message Headers
|
||||
===============
|
||||
|
||||
Sometimes you'll want to add your own headers to a message or modify/remove
|
||||
headers that are already present. You work with the message's HeaderSet to do
|
||||
this.
|
||||
|
||||
Header Basics
|
||||
-------------
|
||||
|
||||
All MIME entities in Swift Mailer -- including the message itself --
|
||||
store their headers in a single object called a HeaderSet. This HeaderSet is
|
||||
retrieved with the ``getHeaders()`` method.
|
||||
|
||||
As mentioned in the previous chapter, everything that forms a part of a message
|
||||
in Swift Mailer is a MIME entity that is represented by an instance of
|
||||
``Swift_Mime_MimeEntity``. This includes -- most notably -- the message object
|
||||
itself, attachments, MIME parts and embedded images. Each of these MIME entities
|
||||
consists of a body and a set of headers that describe the body.
|
||||
|
||||
For all of the "standard" headers in these MIME entities, such as the
|
||||
``Content-Type``, there are named methods for working with them, such as
|
||||
``setContentType()`` and ``getContentType()``. This is because headers are a
|
||||
moderately complex area of the library. Each header has a slightly different
|
||||
required structure that it must meet in order to comply with the standards that
|
||||
govern email (and that are checked by spam blockers etc).
|
||||
|
||||
You fetch the HeaderSet from a MIME entity like so:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$message = Swift_Message::newInstance();
|
||||
|
||||
// Fetch the HeaderSet from a Message object
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
$attachment = Swift_Attachment::fromPath('document.pdf');
|
||||
|
||||
// Fetch the HeaderSet from an attachment object
|
||||
$headers = $attachment->getHeaders();
|
||||
|
||||
The job of the HeaderSet is to contain and manage instances of Header objects.
|
||||
Depending upon the MIME entity the HeaderSet came from, the contents of the
|
||||
HeaderSet will be different, since an attachment for example has a different
|
||||
set of headers to those in a message.
|
||||
|
||||
You can find out what the HeaderSet contains with a quick loop, dumping out
|
||||
the names of the headers:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
foreach ($headers->getAll() as $header) {
|
||||
printf("%s<br />\n", $header->getFieldName());
|
||||
}
|
||||
|
||||
/*
|
||||
Content-Transfer-Encoding
|
||||
Content-Type
|
||||
MIME-Version
|
||||
Date
|
||||
Message-ID
|
||||
From
|
||||
Subject
|
||||
To
|
||||
*/
|
||||
|
||||
You can also dump out the rendered HeaderSet by calling its ``toString()``
|
||||
method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
echo $headers->toString();
|
||||
|
||||
/*
|
||||
Message-ID: <1234869991.499a9ee7f1d5e@swift.generated>
|
||||
Date: Tue, 17 Feb 2009 22:26:31 +1100
|
||||
Subject: Awesome subject!
|
||||
From: sender@example.org
|
||||
To: recipient@example.org
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
*/
|
||||
|
||||
Where the complexity comes in is when you want to modify an existing header.
|
||||
This complexity comes from the fact that each header can be of a slightly
|
||||
different type (such as a Date header, or a header that contains email
|
||||
addresses, or a header that has key-value parameters on it!). Each header in the
|
||||
HeaderSet is an instance of ``Swift_Mime_Header``. They all have common
|
||||
functionality, but knowing exactly what type of header you're working with will
|
||||
allow you a little more control.
|
||||
|
||||
You can determine the type of header by comparing the return value of its
|
||||
``getFieldType()`` method with the constants ``TYPE_TEXT``,
|
||||
``TYPE_PARAMETERIZED``, ``TYPE_DATE``, ``TYPE_MAILBOX``, ``TYPE_ID`` and
|
||||
``TYPE_PATH`` which are defined in ``Swift_Mime_Header``.
|
||||
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
foreach ($headers->getAll() as $header) {
|
||||
switch ($header->getFieldType()) {
|
||||
case Swift_Mime_Header::TYPE_TEXT: $type = 'text';
|
||||
break;
|
||||
case Swift_Mime_Header::TYPE_PARAMETERIZED: $type = 'parameterized';
|
||||
break;
|
||||
case Swift_Mime_Header::TYPE_MAILBOX: $type = 'mailbox';
|
||||
break;
|
||||
case Swift_Mime_Header::TYPE_DATE: $type = 'date';
|
||||
break;
|
||||
case Swift_Mime_Header::TYPE_ID: $type = 'ID';
|
||||
break;
|
||||
case Swift_Mime_Header::TYPE_PATH: $type = 'path';
|
||||
break;
|
||||
}
|
||||
printf("%s: is a %s header<br />\n", $header->getFieldName(), $type);
|
||||
}
|
||||
|
||||
/*
|
||||
Content-Transfer-Encoding: is a text header
|
||||
Content-Type: is a parameterized header
|
||||
MIME-Version: is a text header
|
||||
Date: is a date header
|
||||
Message-ID: is a ID header
|
||||
From: is a mailbox header
|
||||
Subject: is a text header
|
||||
To: is a mailbox header
|
||||
*/
|
||||
|
||||
Headers can be removed from the set, modified within the set, or added to the
|
||||
set.
|
||||
|
||||
The following sections show you how to work with the HeaderSet and explain the
|
||||
details of each implementation of ``Swift_Mime_Header`` that may
|
||||
exist within the HeaderSet.
|
||||
|
||||
Header Types
|
||||
------------
|
||||
|
||||
Because all headers are modeled on different data (dates, addresses, text!)
|
||||
there are different types of Header in Swift Mailer. Swift Mailer attempts to
|
||||
categorize all possible MIME headers into more general groups, defined by a
|
||||
small number of classes.
|
||||
|
||||
Text Headers
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Text headers are the simplest type of Header. They contain textual information
|
||||
with no special information included within it -- for example the Subject
|
||||
header in a message.
|
||||
|
||||
There's nothing particularly interesting about a text header, though it is
|
||||
probably the one you'd opt to use if you need to add a custom header to a
|
||||
message. It represents text just like you'd think it does. If the text
|
||||
contains characters that are not permitted in a message header (such as new
|
||||
lines, or non-ascii characters) then the header takes care of encoding the
|
||||
text so that it can be used.
|
||||
|
||||
No header -- including text headers -- in Swift Mailer is vulnerable to
|
||||
header-injection attacks. Swift Mailer breaks any attempt at header injection by
|
||||
encoding the dangerous data into a non-dangerous form.
|
||||
|
||||
It's easy to add a new text header to a HeaderSet. You do this by calling the
|
||||
HeaderSet's ``addTextHeader()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$message = Swift_Message::newInstance();
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
$headers->addTextHeader('Your-Header-Name', 'the header value');
|
||||
|
||||
Changing the value of an existing text header is done by calling it's
|
||||
``setValue()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$subject = $message->getHeaders()->get('Subject');
|
||||
|
||||
$subject->setValue('new subject');
|
||||
|
||||
When output via ``toString()``, a text header produces something like the
|
||||
following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$subject = $message->getHeaders()->get('Subject');
|
||||
|
||||
$subject->setValue('amazing subject line');
|
||||
|
||||
echo $subject->toString();
|
||||
|
||||
/*
|
||||
|
||||
Subject: amazing subject line
|
||||
|
||||
*/
|
||||
|
||||
If the header contains any characters that are outside of the US-ASCII range
|
||||
however, they will be encoded. This is nothing to be concerned about since
|
||||
mail clients will decode them back.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$subject = $message->getHeaders()->get('Subject');
|
||||
|
||||
$subject->setValue('contains – dash');
|
||||
|
||||
echo $subject->toString();
|
||||
|
||||
/*
|
||||
|
||||
Subject: contains =?utf-8?Q?=E2=80=93?= dash
|
||||
|
||||
*/
|
||||
|
||||
Parameterized Headers
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Parameterized headers are text headers that contain key-value parameters
|
||||
following the textual content. The Content-Type header of a message is a
|
||||
parameterized header since it contains charset information after the content
|
||||
type.
|
||||
|
||||
The parameterized header type is a special type of text header. It extends the
|
||||
text header by allowing additional information to follow it. All of the methods
|
||||
from text headers are available in addition to the methods described here.
|
||||
|
||||
Adding a parameterized header to a HeaderSet is done by using the
|
||||
``addParameterizedHeader()`` method which takes a text value like
|
||||
``addTextHeader()`` but it also accepts an associative array of
|
||||
key-value parameters.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$message = Swift_Message::newInstance();
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
$headers->addParameterizedHeader(
|
||||
'Header-Name', 'header value',
|
||||
array('foo' => 'bar')
|
||||
);
|
||||
|
||||
To change the text value of the header, call it's ``setValue()`` method just as
|
||||
you do with text headers.
|
||||
|
||||
To change the parameters in the header, call the header's ``setParameters()``
|
||||
method or the ``setParameter()`` method (note the pluralization).
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$type = $message->getHeaders()->get('Content-Type');
|
||||
|
||||
// setParameters() takes an associative array
|
||||
$type->setParameters(array(
|
||||
'name' => 'file.txt',
|
||||
'charset' => 'iso-8859-1'
|
||||
));
|
||||
|
||||
// setParameter() takes two args for $key and $value
|
||||
$type->setParameter('charset', 'iso-8859-1');
|
||||
|
||||
When output via ``toString()``, a parameterized header produces something like
|
||||
the following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$type = $message->getHeaders()->get('Content-Type');
|
||||
|
||||
$type->setValue('text/html');
|
||||
$type->setParameter('charset', 'utf-8');
|
||||
|
||||
echo $type->toString();
|
||||
|
||||
/*
|
||||
|
||||
Content-Type: text/html; charset=utf-8
|
||||
|
||||
*/
|
||||
|
||||
If the header contains any characters that are outside of the US-ASCII range
|
||||
however, they will be encoded, just like they are for text headers. This is
|
||||
nothing to be concerned about since mail clients will decode them back.
|
||||
Likewise, if the parameters contain any non-ascii characters they will be
|
||||
encoded so that they can be transmitted safely.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$attachment = Swift_Attachment::newInstance();
|
||||
|
||||
$disp = $attachment->getHeaders()->get('Content-Disposition');
|
||||
|
||||
$disp->setValue('attachment');
|
||||
$disp->setParameter('filename', 'report–may.pdf');
|
||||
|
||||
echo $disp->toString();
|
||||
|
||||
/*
|
||||
|
||||
Content-Disposition: attachment; filename*=utf-8''report%E2%80%93may.pdf
|
||||
|
||||
*/
|
||||
|
||||
Date Headers
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Date headers contains an RFC 2822 formatted date (i.e. what PHP's ``date('r')``
|
||||
returns). They are used anywhere a date or time is needed to be presented as a
|
||||
message header.
|
||||
|
||||
The data on which a date header is modeled is simply a UNIX timestamp such as
|
||||
that returned by ``time()`` or ``strtotime()``. The timestamp is used to create
|
||||
a correctly structured RFC 2822 formatted date such as
|
||||
``Tue, 17 Feb 2009 22:26:31 +1100``.
|
||||
|
||||
The obvious place this header type is used is in the ``Date:`` header of the
|
||||
message itself.
|
||||
|
||||
It's easy to add a new date header to a HeaderSet. You do this by calling
|
||||
the HeaderSet's ``addDateHeader()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$message = Swift_Message::newInstance();
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
$headers->addDateHeader('Your-Header-Name', strtotime('3 days ago'));
|
||||
|
||||
Changing the value of an existing date header is done by calling it's
|
||||
``setTimestamp()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$date = $message->getHeaders()->get('Date');
|
||||
|
||||
$date->setTimestamp(time());
|
||||
|
||||
When output via ``toString()``, a date header produces something like the
|
||||
following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$date = $message->getHeaders()->get('Date');
|
||||
|
||||
echo $date->toString();
|
||||
|
||||
/*
|
||||
|
||||
Date: Wed, 18 Feb 2009 13:35:02 +1100
|
||||
|
||||
*/
|
||||
|
||||
Mailbox (e-mail address) Headers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Mailbox headers contain one or more email addresses, possibly with
|
||||
personalized names attached to them. The data on which they are modeled is
|
||||
represented by an associative array of email addresses and names.
|
||||
|
||||
Mailbox headers are probably the most complex header type to understand in
|
||||
Swift Mailer because they accept their input as an array which can take various
|
||||
forms, as described in the previous chapter.
|
||||
|
||||
All of the headers that contain e-mail addresses in a message -- with the
|
||||
exception of ``Return-Path:`` which has a stricter syntax -- use this header
|
||||
type. That is, ``To:``, ``From:`` etc.
|
||||
|
||||
You add a new mailbox header to a HeaderSet by calling the HeaderSet's
|
||||
``addMailboxHeader()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$message = Swift_Message::newInstance();
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
$headers->addMailboxHeader('Your-Header-Name', array(
|
||||
'person1@example.org' => 'Person Name One',
|
||||
'person2@example.org',
|
||||
'person3@example.org',
|
||||
'person4@example.org' => 'Another named person'
|
||||
));
|
||||
|
||||
Changing the value of an existing mailbox header is done by calling it's
|
||||
``setNameAddresses()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$to = $message->getHeaders()->get('To');
|
||||
|
||||
$to->setNameAddresses(array(
|
||||
'joe@example.org' => 'Joe Bloggs',
|
||||
'john@example.org' => 'John Doe',
|
||||
'no-name@example.org'
|
||||
));
|
||||
|
||||
If you don't wish to concern yourself with the complicated accepted input
|
||||
formats accepted by ``setNameAddresses()`` as described in the previous chapter
|
||||
and you only want to set one or more addresses (not names) then you can just
|
||||
use the ``setAddresses()`` method instead.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$to = $message->getHeaders()->get('To');
|
||||
|
||||
$to->setAddresses(array(
|
||||
'joe@example.org',
|
||||
'john@example.org',
|
||||
'no-name@example.org'
|
||||
));
|
||||
|
||||
.. note::
|
||||
|
||||
Both methods will accept the above input format in practice.
|
||||
|
||||
If all you want to do is set a single address in the header, you can use a
|
||||
string as the input parameter to ``setAddresses()`` and/or
|
||||
``setNameAddresses()``.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$to = $message->getHeaders()->get('To');
|
||||
|
||||
$to->setAddresses('joe-bloggs@example.org');
|
||||
|
||||
When output via ``toString()``, a mailbox header produces something like the
|
||||
following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$to = $message->getHeaders()->get('To');
|
||||
|
||||
$to->setNameAddresses(array(
|
||||
'person1@example.org' => 'Name of Person',
|
||||
'person2@example.org',
|
||||
'person3@example.org' => 'Another Person'
|
||||
));
|
||||
|
||||
echo $to->toString();
|
||||
|
||||
/*
|
||||
|
||||
To: Name of Person <person1@example.org>, person2@example.org, Another Person
|
||||
<person3@example.org>
|
||||
|
||||
*/
|
||||
|
||||
ID Headers
|
||||
~~~~~~~~~~
|
||||
|
||||
ID headers contain identifiers for the entity (or the message). The most
|
||||
notable ID header is the Message-ID header on the message itself.
|
||||
|
||||
An ID that exists inside an ID header looks more-or-less less like an email
|
||||
address. For example, ``<1234955437.499becad62ec2@example.org>``.
|
||||
The part to the left of the @ sign is usually unique, based on the current time
|
||||
and some random factor. The part on the right is usually a domain name.
|
||||
|
||||
Any ID passed to the header's ``setId()`` method absolutely MUST conform to
|
||||
this structure, otherwise you'll get an Exception thrown at you by Swift Mailer
|
||||
(a ``Swift_RfcComplianceException``). This is to ensure that the generated
|
||||
email complies with relevant RFC documents and therefore is less likely to be
|
||||
blocked as spam.
|
||||
|
||||
It's easy to add a new ID header to a HeaderSet. You do this by calling
|
||||
the HeaderSet's ``addIdHeader()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$message = Swift_Message::newInstance();
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
$headers->addIdHeader('Your-Header-Name', '123456.unqiue@example.org');
|
||||
|
||||
Changing the value of an existing ID header is done by calling its
|
||||
``setId()`` method::
|
||||
|
||||
$msgId = $message->getHeaders()->get('Message-ID');
|
||||
|
||||
$msgId->setId(time() . '.' . uniqid('thing') . '@example.org');
|
||||
|
||||
When output via ``toString()``, an ID header produces something like the
|
||||
following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$msgId = $message->getHeaders()->get('Message-ID');
|
||||
|
||||
echo $msgId->toString();
|
||||
|
||||
/*
|
||||
|
||||
Message-ID: <1234955437.499becad62ec2@example.org>
|
||||
|
||||
*/
|
||||
|
||||
Path Headers
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Path headers are like very-restricted mailbox headers. They contain a single
|
||||
email address with no associated name. The Return-Path header of a message is
|
||||
a path header.
|
||||
|
||||
You add a new path header to a HeaderSet by calling the HeaderSet's
|
||||
``addPathHeader()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$message = Swift_Message::newInstance();
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
$headers->addPathHeader('Your-Header-Name', 'person@example.org');
|
||||
|
||||
Changing the value of an existing path header is done by calling its
|
||||
``setAddress()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$return = $message->getHeaders()->get('Return-Path');
|
||||
|
||||
$return->setAddress('my-address@example.org');
|
||||
|
||||
When output via ``toString()``, a path header produces something like the
|
||||
following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$return = $message->getHeaders()->get('Return-Path');
|
||||
|
||||
$return->setAddress('person@example.org');
|
||||
|
||||
echo $return->toString();
|
||||
|
||||
/*
|
||||
|
||||
Return-Path: <person@example.org>
|
||||
|
||||
*/
|
||||
|
||||
Header Operations
|
||||
-----------------
|
||||
|
||||
Working with the headers in a message involves knowing how to use the methods
|
||||
on the HeaderSet and on the individual Headers within the HeaderSet.
|
||||
|
||||
Adding new Headers
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
New headers can be added to the HeaderSet by using one of the provided
|
||||
``add..Header()`` methods.
|
||||
|
||||
To add a header to a MIME entity (such as the message):
|
||||
|
||||
Get the HeaderSet from the entity by via its ``getHeaders()`` method.
|
||||
|
||||
* Add the header to the HeaderSet by calling one of the ``add..Header()``
|
||||
methods.
|
||||
|
||||
The added header will appear in the message when it is sent.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Adding a custom header to a message
|
||||
$message = Swift_Message::newInstance();
|
||||
$headers = $message->getHeaders();
|
||||
$headers->addTextHeader('X-Mine', 'something here');
|
||||
|
||||
// Adding a custom header to an attachment
|
||||
$attachment = Swift_Attachment::fromPath('/path/to/doc.pdf');
|
||||
$attachment->getHeaders()->addDateHeader('X-Created-Time', time());
|
||||
|
||||
Retrieving Headers
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Headers are retrieved through the HeaderSet's ``get()`` and ``getAll()``
|
||||
methods.
|
||||
|
||||
To get a header, or several headers from a MIME entity:
|
||||
|
||||
* Get the HeaderSet from the entity by via its ``getHeaders()`` method.
|
||||
|
||||
* Get the header(s) from the HeaderSet by calling either ``get()`` or
|
||||
``getAll()``.
|
||||
|
||||
When using ``get()`` a single header is returned that matches the name (case
|
||||
insensitive) that is passed to it. When using ``getAll()`` with a header name,
|
||||
an array of headers with that name are returned. Calling ``getAll()`` with no
|
||||
arguments returns an array of all headers present in the entity.
|
||||
|
||||
.. note::
|
||||
|
||||
It's valid for some headers to appear more than once in a message (e.g.
|
||||
the Received header). For this reason ``getAll()`` exists to fetch all
|
||||
headers with a specified name. In addition, ``get()`` accepts an optional
|
||||
numerical index, starting from zero to specify which header you want more
|
||||
specifically.
|
||||
|
||||
.. note::
|
||||
|
||||
If you want to modify the contents of the header and you don't know for
|
||||
sure what type of header it is then you may need to check the type by
|
||||
calling its ``getFieldType()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
// Get the To: header
|
||||
$toHeader = $headers->get('To');
|
||||
|
||||
// Get all headers named "X-Foo"
|
||||
$fooHeaders = $headers->getAll('X-Foo');
|
||||
|
||||
// Get the second header named "X-Foo"
|
||||
$foo = $headers->get('X-Foo', 1);
|
||||
|
||||
// Get all headers that are present
|
||||
$all = $headers->getAll();
|
||||
|
||||
Check if a Header Exists
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can check if a named header is present in a HeaderSet by calling its
|
||||
``has()`` method.
|
||||
|
||||
To check if a header exists:
|
||||
|
||||
* Get the HeaderSet from the entity by via its ``getHeaders()`` method.
|
||||
|
||||
* Call the HeaderSet's ``has()`` method specifying the header you're looking
|
||||
for.
|
||||
|
||||
If the header exists, ``true`` will be returned or ``false`` if not.
|
||||
|
||||
.. note::
|
||||
|
||||
It's valid for some headers to appear more than once in a message (e.g.
|
||||
the Received header). For this reason ``has()`` accepts an optional
|
||||
numerical index, starting from zero to specify which header you want to
|
||||
check more specifically.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
// Check if the To: header exists
|
||||
if ($headers->has('To')) {
|
||||
echo 'To: exists';
|
||||
}
|
||||
|
||||
// Check if an X-Foo header exists twice (i.e. check for the 2nd one)
|
||||
if ($headers->has('X-Foo', 1)) {
|
||||
echo 'Second X-Foo header exists';
|
||||
}
|
||||
|
||||
Removing Headers
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Removing a Header from the HeaderSet is done by calling the HeaderSet's
|
||||
``remove()`` or ``removeAll()`` methods.
|
||||
|
||||
To remove an existing header:
|
||||
|
||||
* Get the HeaderSet from the entity by via its ``getHeaders()`` method.
|
||||
|
||||
* Call the HeaderSet's ``remove()`` or ``removeAll()`` methods specifying the
|
||||
header you want to remove.
|
||||
|
||||
When calling ``remove()`` a single header will be removed. When calling
|
||||
``removeAll()`` all headers with the given name will be removed. If no headers
|
||||
exist with the given name, no errors will occur.
|
||||
|
||||
.. note::
|
||||
|
||||
It's valid for some headers to appear more than once in a message (e.g.
|
||||
the Received header). For this reason ``remove()`` accepts an optional
|
||||
numerical index, starting from zero to specify which header you want to
|
||||
check more specifically. For the same reason, ``removeAll()`` exists to
|
||||
remove all headers that have the given name.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
// Remove the Subject: header
|
||||
$headers->remove('Subject');
|
||||
|
||||
// Remove all X-Foo headers
|
||||
$headers->removeAll('X-Foo');
|
||||
|
||||
// Remove only the second X-Foo header
|
||||
$headers->remove('X-Foo', 1);
|
||||
|
||||
Modifying a Header's Content
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To change a Header's content you should know what type of header it is and then
|
||||
call it's appropriate setter method. All headers also have a
|
||||
``setFieldBodyModel()`` method that accepts a mixed parameter and delegates to
|
||||
the correct setter.
|
||||
|
||||
To modify an existing header:
|
||||
|
||||
* Get the HeaderSet from the entity by via its ``getHeaders()`` method.
|
||||
|
||||
* Get the Header by using the HeaderSet's ``get()``.
|
||||
|
||||
* Call the Header's appropriate setter method or call the header's
|
||||
``setFieldBodyModel()`` method.
|
||||
|
||||
The header will be updated inside the HeaderSet and the changes will be seen
|
||||
when the message is sent.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
|
||||
// Change the Subject: header
|
||||
$subj = $headers->get('Subject');
|
||||
$subj->setValue('new subject here');
|
||||
|
||||
// Change the To: header
|
||||
$to = $headers->get('To');
|
||||
$to->setNameAddresses(array(
|
||||
'person@example.org' => 'Person',
|
||||
'thing@example.org'
|
||||
));
|
||||
|
||||
// Using the setFieldBodyModel() just delegates to the correct method
|
||||
// So here to calls setNameAddresses()
|
||||
$to->setFieldBodyModel(array(
|
||||
'person@example.org' => 'Person',
|
||||
'thing@example.org'
|
||||
));
|
||||
@@ -1,44 +0,0 @@
|
||||
Getting Help
|
||||
============
|
||||
|
||||
There are a number of ways you can get help when using Swift Mailer, depending
|
||||
upon the nature of your problem. For bug reports and feature requests create a
|
||||
new ticket in GitHub. For general advice ask on the Google Group
|
||||
(swiftmailer).
|
||||
|
||||
Submitting Bugs & Feature Requests
|
||||
----------------------------------
|
||||
|
||||
Bugs and feature requests should be posted on GitHub.
|
||||
|
||||
If you post a bug or request a feature in the forum, or on the Google Group
|
||||
you will most likely be asked to create a ticket in `GitHub`_ since it is
|
||||
simply not feasible to manage such requests from a number of a different
|
||||
sources.
|
||||
|
||||
When you go to GitHub you will be asked to create a username and password
|
||||
before you can create a ticket. This is free and takes very little time.
|
||||
|
||||
When you create your ticket, do not assign it to any milestones. A developer
|
||||
will assess your ticket and re-assign it as needed.
|
||||
|
||||
If your ticket is reporting a bug present in the current version, which was
|
||||
not present in the previous version please include the tag "regression" in
|
||||
your ticket.
|
||||
|
||||
GitHub will update you when work is performed on your ticket.
|
||||
|
||||
Ask on the Google Group
|
||||
-----------------------
|
||||
|
||||
You can seek advice at Google Groups, within the "swiftmailer" `group`_.
|
||||
|
||||
You can post messages to this group if you want help, or there's something you
|
||||
wish to discuss with the developers and with other users.
|
||||
|
||||
This is probably the fastest way to get help since it is primarily email-based
|
||||
for most users, though bug reports should not be posted here since they may
|
||||
not be resolved.
|
||||
|
||||
.. _`GitHub`: https://github.com/swiftmailer/swiftmailer/issues
|
||||
.. _`group`: http://groups.google.com/group/swiftmailer
|
||||
@@ -1,46 +0,0 @@
|
||||
Including Swift Mailer (Autoloading)
|
||||
====================================
|
||||
|
||||
If you are using Composer, Swift Mailer will be automatically autoloaded.
|
||||
|
||||
If not, you can use the built-in autoloader by requiring the
|
||||
``swift_required.php`` file::
|
||||
|
||||
require_once '/path/to/swift-mailer/lib/swift_required.php';
|
||||
|
||||
/* rest of code goes here */
|
||||
|
||||
If you want to override the default Swift Mailer configuration, call the
|
||||
``init()`` method on the ``Swift`` class and pass it a valid PHP callable (a
|
||||
PHP function name, a PHP 5.3 anonymous function, ...)::
|
||||
|
||||
require_once '/path/to/swift-mailer/lib/swift_required.php';
|
||||
|
||||
function swiftmailer_configurator() {
|
||||
// configure Swift Mailer
|
||||
|
||||
Swift_DependencyContainer::getInstance()->...
|
||||
Swift_Preferences::getInstance()->...
|
||||
}
|
||||
|
||||
Swift::init('swiftmailer_configurator');
|
||||
|
||||
/* rest of code goes here */
|
||||
|
||||
The advantage of using the ``init()`` method is that your code will be
|
||||
executed only if you use Swift Mailer in your script.
|
||||
|
||||
.. note::
|
||||
|
||||
While Swift Mailer's autoloader is designed to play nicely with other
|
||||
autoloaders, sometimes you may have a need to avoid using Swift Mailer's
|
||||
autoloader and use your own instead. Include the ``swift_init.php``
|
||||
instead of the ``swift_required.php`` if you need to do this. The very
|
||||
minimum include is the ``swift_init.php`` file since Swift Mailer will not
|
||||
work without the dependency injection this file sets up:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once '/path/to/swift-mailer/lib/swift_init.php';
|
||||
|
||||
/* rest of code goes here */
|
||||
@@ -1,16 +0,0 @@
|
||||
Swiftmailer
|
||||
===========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
introduction
|
||||
overview
|
||||
installing
|
||||
help-resources
|
||||
including-the-files
|
||||
messages
|
||||
headers
|
||||
sending
|
||||
plugins
|
||||
japanese
|
||||
@@ -1,89 +0,0 @@
|
||||
Installing the Library
|
||||
======================
|
||||
|
||||
Installing with Composer
|
||||
------------------------
|
||||
|
||||
The recommended way to install Swiftmailer is via Composer:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php composer.phar require swiftmailer/swiftmailer @stable
|
||||
|
||||
Installing from Git
|
||||
-------------------
|
||||
|
||||
It's possible to download and install Swift Mailer directly from github.com if
|
||||
you want to keep up-to-date with ease.
|
||||
|
||||
Swift Mailer's source code is kept in a git repository at github.com so you
|
||||
can get the source directly from the repository.
|
||||
|
||||
.. note::
|
||||
|
||||
You do not need to have git installed to use Swift Mailer from GitHub. If
|
||||
you don't have git installed, go to `GitHub`_ and click the "Download"
|
||||
button.
|
||||
|
||||
Cloning the Repository
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The repository can be cloned from git://github.com/swiftmailer/swiftmailer.git
|
||||
using the ``git clone`` command.
|
||||
|
||||
You will need to have ``git`` installed before you can use the
|
||||
``git clone`` command.
|
||||
|
||||
To clone the repository:
|
||||
|
||||
* Open your favorite terminal environment (command line).
|
||||
|
||||
* Move to the directory you want to clone to.
|
||||
|
||||
* Run the command ``git clone git://github.com/swiftmailer/swiftmailer.git
|
||||
swiftmailer``.
|
||||
|
||||
The source code will be downloaded into a directory called "swiftmailer".
|
||||
|
||||
The example shows the process on a UNIX-like system such as Linux, BSD or Mac
|
||||
OS X.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd source_code/
|
||||
$ git clone git://github.com/swiftmailer/swiftmailer.git swiftmailer
|
||||
Initialized empty Git repository in /Users/chris/source_code/swiftmailer/.git/
|
||||
remote: Counting objects: 6815, done.
|
||||
remote: Compressing objects: 100% (2761/2761), done.
|
||||
remote: Total 6815 (delta 3641), reused 6326 (delta 3286)
|
||||
Receiving objects: 100% (6815/6815), 4.35 MiB | 162 KiB/s, done.
|
||||
Resolving deltas: 100% (3641/3641), done.
|
||||
Checking out files: 100% (1847/1847), done.
|
||||
$ cd swiftmailer/
|
||||
$ ls
|
||||
CHANGES LICENSE ...
|
||||
$
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
Swift Mailer does not work when used with function overloading as implemented
|
||||
by ``mbstring`` (``mbstring.func_overload`` set to ``2``). A workaround is to
|
||||
temporarily change the internal encoding to ``ASCII`` when sending an email:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2)
|
||||
{
|
||||
$mbEncoding = mb_internal_encoding();
|
||||
mb_internal_encoding('ASCII');
|
||||
}
|
||||
|
||||
// Create your message and send it with Swift Mailer
|
||||
|
||||
if (isset($mbEncoding))
|
||||
{
|
||||
mb_internal_encoding($mbEncoding);
|
||||
}
|
||||
|
||||
.. _`GitHub`: http://github.com/swiftmailer/swiftmailer
|
||||
@@ -1,135 +0,0 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
Swift Mailer is a component-based library for sending e-mails from PHP
|
||||
applications.
|
||||
|
||||
Organization of this Book
|
||||
-------------------------
|
||||
|
||||
This book has been written so that those who need information quickly are able
|
||||
to find what they need, and those who wish to learn more advanced topics can
|
||||
read deeper into each chapter.
|
||||
|
||||
The book begins with an overview of Swift Mailer, discussing what's included
|
||||
in the package and preparing you for the remainder of the book.
|
||||
|
||||
It is possible to read this user guide just like any other book (from
|
||||
beginning to end). Each chapter begins with a discussion of the contents it
|
||||
contains, followed by a short code sample designed to give you a head start.
|
||||
As you get further into a chapter you will learn more about Swift Mailer's
|
||||
capabilities, but often you will be able to head directly to the topic you
|
||||
wish to learn about.
|
||||
|
||||
Throughout this book you will be presented with code samples, which most
|
||||
people should find ample to implement Swift Mailer appropriately in their own
|
||||
projects. We will also use diagrams where appropriate, and where we believe
|
||||
readers may find it helpful we will discuss some related theory, including
|
||||
reference to certain documents you are able to find online.
|
||||
|
||||
Code Samples
|
||||
------------
|
||||
|
||||
Code samples presented in this book will be displayed on a different colored
|
||||
background in a monospaced font. Samples are not to be taken as copy & paste
|
||||
code snippets.
|
||||
|
||||
Code examples are used through the book to clarify what is written in text.
|
||||
They will sometimes be usable as-is, but they should always be taken as
|
||||
outline/pseudo code only.
|
||||
|
||||
A code sample will look like this::
|
||||
|
||||
class AClass
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
// A Comment
|
||||
$obj = new AClass($arg1, $arg2, ... );
|
||||
|
||||
/* A note about another way of doing something
|
||||
$obj = AClass::newInstance($arg1, $arg2, ... );
|
||||
|
||||
*/
|
||||
|
||||
The presence of 3 dots ``...`` in a code sample indicates that we have left
|
||||
out a chunk of the code for brevity, they are not actually part of the code.
|
||||
|
||||
We will often place multi-line comments ``/* ... */`` in the code so that we
|
||||
can show alternative ways of achieving the same result.
|
||||
|
||||
You should read the code examples given and try to understand them. They are
|
||||
kept concise so that you are not overwhelmed with information.
|
||||
|
||||
History of Swift Mailer
|
||||
-----------------------
|
||||
|
||||
Swift Mailer began back in 2005 as a one-class project for sending mail over
|
||||
SMTP. It has since grown into the flexible component-based library that is in
|
||||
development today.
|
||||
|
||||
Chris Corbyn first posted Swift Mailer on a web forum asking for comments from
|
||||
other developers. It was never intended as a fully supported open source
|
||||
project, but members of the forum began to adopt it and make use of it.
|
||||
|
||||
Very quickly feature requests were coming for the ability to add attachments
|
||||
and use SMTP authentication, along with a number of other "obvious" missing
|
||||
features. Considering the only alternative was PHPMailer it seemed like a good
|
||||
time to bring some fresh tools to the table. Chris began working towards a
|
||||
more component based, PHP5-like approach unlike the existing single-class,
|
||||
legacy PHP4 approach taken by PHPMailer.
|
||||
|
||||
Members of the forum offered a lot of advice and critique on the code as he
|
||||
worked through this project and released versions 2 and 3 of the library in
|
||||
2005 and 2006, which by then had been broken down into smaller classes
|
||||
offering more flexibility and supporting plugins. To this day the Swift Mailer
|
||||
team still receive a lot of feature requests from users both on the forum and
|
||||
in by email.
|
||||
|
||||
Until 2008 Chris was the sole developer of Swift Mailer, but entering 2009 he
|
||||
gained the support of two experienced developers well-known to him: Paul
|
||||
Annesley and Christopher Thompson. This has been an extremely welcome change.
|
||||
|
||||
As of September 2009, Chris handed over the maintenance of Swift Mailer to
|
||||
Fabien Potencier.
|
||||
|
||||
Now 2009 and in its fourth major version Swift Mailer is more object-oriented
|
||||
and flexible than ever, both from a usability standpoint and from a
|
||||
development standpoint.
|
||||
|
||||
By no means is Swift Mailer ready to call "finished". There are still many
|
||||
features that can be added to the library along with the constant refactoring
|
||||
that happens behind the scenes.
|
||||
|
||||
It's a Library!
|
||||
---------------
|
||||
|
||||
Swift Mailer is not an application - it's a library.
|
||||
|
||||
To most experienced developers this is probably an obvious point to make, but
|
||||
it's certainly worth mentioning. Many people often contact us having gotten
|
||||
the completely wrong end of the stick in terms of what Swift Mailer is
|
||||
actually for.
|
||||
|
||||
It's not an application. It does not have a graphical user interface. It
|
||||
cannot be opened in your web browser directly.
|
||||
|
||||
It's a library (or a framework if you like). It provides a whole lot of
|
||||
classes that do some very complicated things, so that you don't have to. You
|
||||
"use" Swift Mailer within an application so that your application can have the
|
||||
ability to send emails.
|
||||
|
||||
The component-based structure of the library means that you are free to
|
||||
implement it in a number of different ways and that you can pick and choose
|
||||
what you want to use.
|
||||
|
||||
An application on the other hand (such as a blog or a forum) is already "put
|
||||
together" in a particular way, (usually) provides a graphical user interface
|
||||
and most likely doesn't offer a great deal of integration with your own
|
||||
application.
|
||||
|
||||
Embrace the structure of the library and use the components it offers to your
|
||||
advantage. Learning what the components do, rather than blindly copying and
|
||||
pasting existing code will put you in a great position to build a powerful
|
||||
application!
|
||||
@@ -1,22 +0,0 @@
|
||||
Using Swift Mailer for Japanese Emails
|
||||
======================================
|
||||
|
||||
To send emails in Japanese, you need to tweak the default configuration.
|
||||
|
||||
After requiring the Swift Mailer autoloader (by including the
|
||||
``swift_required.php`` file), call the ``Swift::init()`` method with the
|
||||
following code::
|
||||
|
||||
require_once '/path/to/swift-mailer/lib/swift_required.php';
|
||||
|
||||
Swift::init(function () {
|
||||
Swift_DependencyContainer::getInstance()
|
||||
->register('mime.qpheaderencoder')
|
||||
->asAliasOf('mime.base64headerencoder');
|
||||
|
||||
Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
|
||||
});
|
||||
|
||||
/* rest of code goes here */
|
||||
|
||||
That's all!
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,159 +0,0 @@
|
||||
Library Overview
|
||||
================
|
||||
|
||||
Most features (and more) of your every day mail client software are provided
|
||||
by Swift Mailer, using object-oriented PHP code as the interface.
|
||||
|
||||
In this chapter we will take a short tour of the various components, which put
|
||||
together form the Swift Mailer library as a whole. You will learn key
|
||||
terminology used throughout the rest of this book and you will gain a little
|
||||
understanding of the classes you will work with as you integrate Swift Mailer
|
||||
into your application.
|
||||
|
||||
This chapter is intended to prepare you for the information contained in the
|
||||
subsequent chapters of this book. You may choose to skip this chapter if you
|
||||
are fairly technically minded, though it is likely to save you some time in
|
||||
the long run if you at least read between the lines here.
|
||||
|
||||
System Requirements
|
||||
-------------------
|
||||
|
||||
The basic requirements to operate Swift Mailer are extremely minimal and
|
||||
easily achieved. Historically, Swift Mailer has supported both PHP 4 and PHP 5
|
||||
by following a parallel development workflow. Now in it's fourth major
|
||||
version, and Swift Mailer operates on servers running PHP 5.3.3 or higher.
|
||||
|
||||
The library aims to work with as many PHP 5 projects as possible:
|
||||
|
||||
* PHP 5.3.3 or higher, with the SPL extension (standard)
|
||||
|
||||
* Limited network access to connect to remote SMTP servers
|
||||
|
||||
* 8 MB or more memory limit (Swift Mailer uses around 2 MB)
|
||||
|
||||
Component Breakdown
|
||||
-------------------
|
||||
|
||||
Swift Mailer is made up of many classes. Each of these classes can be grouped
|
||||
into a general "component" group which describes the task it is designed to
|
||||
perform.
|
||||
|
||||
We'll take a brief look at the components which form Swift Mailer in this
|
||||
section of the book.
|
||||
|
||||
The Mailer
|
||||
~~~~~~~~~~
|
||||
|
||||
The mailer class, ``Swift_Mailer`` is the central class in the library where
|
||||
all of the other components meet one another. ``Swift_Mailer`` acts as a sort
|
||||
of message dispatcher, communicating with the underlying Transport to deliver
|
||||
your Message to all intended recipients.
|
||||
|
||||
If you were to dig around in the source code for Swift Mailer you'd notice
|
||||
that ``Swift_Mailer`` itself is pretty bare. It delegates to other objects for
|
||||
most tasks and in theory, if you knew the internals of Swift Mailer well you
|
||||
could by-pass this class entirely. We wouldn't advise doing such a thing
|
||||
however -- there are reasons this class exists:
|
||||
|
||||
* for consistency, regardless of the Transport used
|
||||
|
||||
* to provide abstraction from the internals in the event internal API changes
|
||||
are made
|
||||
|
||||
* to provide convenience wrappers around aspects of the internal API
|
||||
|
||||
An instance of ``Swift_Mailer`` is created by the developer before sending any
|
||||
Messages.
|
||||
|
||||
Transports
|
||||
~~~~~~~~~~
|
||||
|
||||
Transports are the classes in Swift Mailer that are responsible for
|
||||
communicating with a service in order to deliver a Message. There are several
|
||||
types of Transport in Swift Mailer, all of which implement the Swift_Transport
|
||||
interface and offer underlying start(), stop() and send() methods.
|
||||
|
||||
Typically you will not need to know how a Transport works under-the-surface,
|
||||
you will only need to know how to create an instance of one, and which one to
|
||||
use for your environment.
|
||||
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Class | Features | Pros/cons |
|
||||
+=================================+=============================================================================================+===============================================================================================================================================+
|
||||
| ``Swift_SmtpTransport`` | Sends messages over SMTP; Supports Authentication; Supports Encryption | Very portable; Pleasingly predictable results; Provides good feedback |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``Swift_SendmailTransport`` | Communicates with a locally installed ``sendmail`` executable (Linux/UNIX) | Quick time-to-run; Provides less-accurate feedback than SMTP; Requires ``sendmail`` installation |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``Swift_LoadBalancedTransport`` | Cycles through a collection of the other Transports to manage load-reduction | Provides graceful fallback if one Transport fails (e.g. an SMTP server is down); Keeps the load on remote services down by spreading the work |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``Swift_FailoverTransport`` | Works in conjunction with a collection of the other Transports to provide high-availability | Provides graceful fallback if one Transport fails (e.g. an SMTP server is down) |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
MIME Entities
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Everything that forms part of a Message is called a MIME Entity. All MIME
|
||||
entities in Swift Mailer share a common set of features. There are various
|
||||
types of MIME entity that serve different purposes such as Attachments and
|
||||
MIME parts.
|
||||
|
||||
An e-mail message is made up of several relatively simple entities that are
|
||||
combined in different ways to achieve different results. All of these entities
|
||||
have the same fundamental outline but serve a different purpose. The Message
|
||||
itself can be defined as a MIME entity, an Attachment is a MIME entity, all
|
||||
MIME parts are MIME entities -- and so on!
|
||||
|
||||
The basic units of each MIME entity -- be it the Message itself, or an
|
||||
Attachment -- are its Headers and its body:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Other-Header: Another value
|
||||
|
||||
The body content itself
|
||||
|
||||
The Headers of a MIME entity, and its body must conform to some strict
|
||||
standards defined by various RFC documents. Swift Mailer ensures that these
|
||||
specifications are followed by using various types of object, including
|
||||
Encoders and different Header types to generate the entity.
|
||||
|
||||
Each MIME component implements the base ``Swift_Mime_MimeEntity`` interface,
|
||||
which offers methods for retrieving Headers, adding new Headers, changing the
|
||||
Encoder, updating the body and so on!
|
||||
|
||||
All MIME entities have one Header in common -- the Content-Type Header,
|
||||
updated with the entity's ``setContentType()`` method.
|
||||
|
||||
Encoders
|
||||
~~~~~~~~
|
||||
|
||||
Encoders are used to transform the content of Messages generated in Swift
|
||||
Mailer into a format that is safe to send across the internet and that
|
||||
conforms to RFC specifications.
|
||||
|
||||
Generally speaking you will not need to interact with the Encoders in Swift
|
||||
Mailer -- the correct settings will be handled by the library itself.
|
||||
However they are probably worth a brief mention in the event that you do want
|
||||
to play with them.
|
||||
|
||||
Both the Headers and the body of all MIME entities (including the Message
|
||||
itself) use Encoders to ensure the data they contain can be sent over the
|
||||
internet without becoming corrupted or misinterpreted.
|
||||
|
||||
There are two types of Encoder: Base64 and Quoted-Printable.
|
||||
|
||||
Plugins
|
||||
~~~~~~~
|
||||
|
||||
Plugins exist to extend, or modify the behaviour of Swift Mailer. They respond
|
||||
to Events that are fired within the Transports during sending.
|
||||
|
||||
There are a number of Plugins provided as part of the base Swift Mailer
|
||||
package and they all follow a common interface to respond to Events fired
|
||||
within the library. Interfaces are provided to "listen" to each type of Event
|
||||
fired and to act as desired when a listened-to Event occurs.
|
||||
|
||||
Although several plugins are provided with Swift Mailer out-of-the-box, the
|
||||
Events system has been specifically designed to make it easy for experienced
|
||||
object-oriented developers to write their own plugins in order to achieve
|
||||
goals that may not be possible with the base library.
|
||||
@@ -1,385 +0,0 @@
|
||||
Plugins
|
||||
=======
|
||||
|
||||
Plugins are provided with Swift Mailer and can be used to extend the behavior
|
||||
of the library in situations where using simple class inheritance would be more complex.
|
||||
|
||||
AntiFlood Plugin
|
||||
----------------
|
||||
|
||||
Many SMTP servers have limits on the number of messages that may be sent
|
||||
during any single SMTP connection. The AntiFlood plugin provides a way to stay
|
||||
within this limit while still managing a large number of emails.
|
||||
|
||||
A typical limit for a single connection is 100 emails. If the server you
|
||||
connect to imposes such a limit, it expects you to disconnect after that
|
||||
number of emails has been sent. You could manage this manually within a loop,
|
||||
but the AntiFlood plugin provides the necessary wrapper code so that you don't
|
||||
need to worry about this logic.
|
||||
|
||||
Regardless of limits imposed by the server, it's usually a good idea to be
|
||||
conservative with the resources of the SMTP server. Sending will become
|
||||
sluggish if the server is being over-used so using the AntiFlood plugin will
|
||||
not be a bad idea even if no limits exist.
|
||||
|
||||
The AntiFlood plugin's logic is basically to disconnect and the immediately
|
||||
re-connect with the SMTP server every X number of emails sent, where X is a
|
||||
number you specify to the plugin.
|
||||
|
||||
You can also specify a time period in seconds that Swift Mailer should pause
|
||||
for between the disconnect/re-connect process. It's a good idea to pause for a
|
||||
short time (say 30 seconds every 100 emails) simply to give the SMTP server a
|
||||
chance to process its queue and recover some resources.
|
||||
|
||||
Using the AntiFlood Plugin
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The AntiFlood Plugin -- like all plugins -- is added with the Mailer class's
|
||||
``registerPlugin()`` method. It takes two constructor parameters: the number of
|
||||
emails to pause after, and optionally the number of seconds to pause for.
|
||||
|
||||
To use the AntiFlood plugin:
|
||||
|
||||
* Create an instance of the Mailer using any Transport you choose.
|
||||
|
||||
* Create an instance of the ``Swift_Plugins_AntiFloodPlugin`` class, passing
|
||||
in one or two constructor parameters.
|
||||
|
||||
* Register the plugin using the Mailer's ``registerPlugin()`` method.
|
||||
|
||||
* Continue using Swift Mailer to send messages as normal.
|
||||
|
||||
When Swift Mailer sends messages it will count the number of messages that
|
||||
have been sent since the last re-connect. Once the number hits your specified
|
||||
threshold it will disconnect and re-connect, optionally pausing for a
|
||||
specified amount of time.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once 'lib/swift_required.php';
|
||||
|
||||
// Create the Mailer using any Transport
|
||||
$mailer = Swift_Mailer::newInstance(
|
||||
Swift_SmtpTransport::newInstance('smtp.example.org', 25)
|
||||
);
|
||||
|
||||
// Use AntiFlood to re-connect after 100 emails
|
||||
$mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100));
|
||||
|
||||
// And specify a time in seconds to pause for (30 secs)
|
||||
$mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100, 30));
|
||||
|
||||
// Continue sending as normal
|
||||
for ($lotsOfRecipients as $recipient) {
|
||||
...
|
||||
|
||||
$mailer->send( ... );
|
||||
}
|
||||
|
||||
Throttler Plugin
|
||||
----------------
|
||||
|
||||
If your SMTP server has restrictions in place to limit the rate at which you
|
||||
send emails, then your code will need to be aware of this rate-limiting. The
|
||||
Throttler plugin makes Swift Mailer run at a rate-limited speed.
|
||||
|
||||
Many shared hosts don't open their SMTP servers as a free-for-all. Usually
|
||||
they have policies in place (probably to discourage spammers) that only allow
|
||||
you to send a fixed number of emails per-hour/day.
|
||||
|
||||
The Throttler plugin supports two modes of rate-limiting and with each, you
|
||||
will need to do that math to figure out the values you want. The plugin can
|
||||
limit based on the number of emails per minute, or the number of
|
||||
bytes-transferred per-minute.
|
||||
|
||||
Using the Throttler Plugin
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Throttler Plugin -- like all plugins -- is added with the Mailer class'
|
||||
``registerPlugin()`` method. It has two required constructor parameters that
|
||||
tell it how to do its rate-limiting.
|
||||
|
||||
To use the Throttler plugin:
|
||||
|
||||
* Create an instance of the Mailer using any Transport you choose.
|
||||
|
||||
* Create an instance of the ``Swift_Plugins_ThrottlerPlugin`` class, passing
|
||||
the number of emails, or bytes you wish to limit by, along with the mode
|
||||
you're using.
|
||||
|
||||
* Register the plugin using the Mailer's ``registerPlugin()`` method.
|
||||
|
||||
* Continue using Swift Mailer to send messages as normal.
|
||||
|
||||
When Swift Mailer sends messages it will keep track of the rate at which sending
|
||||
messages is occurring. If it realises that sending is happening too fast, it
|
||||
will cause your program to ``sleep()`` for enough time to average out the rate.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once 'lib/swift_required.php';
|
||||
|
||||
// Create the Mailer using any Transport
|
||||
$mailer = Swift_Mailer::newInstance(
|
||||
Swift_SmtpTransport::newInstance('smtp.example.org', 25)
|
||||
);
|
||||
|
||||
// Rate limit to 100 emails per-minute
|
||||
$mailer->registerPlugin(new Swift_Plugins_ThrottlerPlugin(
|
||||
100, Swift_Plugins_ThrottlerPlugin::MESSAGES_PER_MINUTE
|
||||
));
|
||||
|
||||
// Rate limit to 10MB per-minute
|
||||
$mailer->registerPlugin(new Swift_Plugins_ThrottlerPlugin(
|
||||
1024 * 1024 * 10, Swift_Plugins_ThrottlerPlugin::BYTES_PER_MINUTE
|
||||
));
|
||||
|
||||
// Continue sending as normal
|
||||
for ($lotsOfRecipients as $recipient) {
|
||||
...
|
||||
|
||||
$mailer->send( ... );
|
||||
}
|
||||
|
||||
Logger Plugin
|
||||
-------------
|
||||
|
||||
The Logger plugins helps with debugging during the process of sending. It can
|
||||
help to identify why an SMTP server is rejecting addresses, or any other
|
||||
hard-to-find problems that may arise.
|
||||
|
||||
The Logger plugin comes in two parts. There's the plugin itself, along with
|
||||
one of a number of possible Loggers that you may choose to use. For example,
|
||||
the logger may output messages directly in realtime, or it may capture
|
||||
messages in an array.
|
||||
|
||||
One other notable feature is the way in which the Logger plugin changes
|
||||
Exception messages. If Exceptions are being thrown but the error message does
|
||||
not provide conclusive information as to the source of the problem (such as an
|
||||
ambiguous SMTP error) the Logger plugin includes the entire SMTP transcript in
|
||||
the error message so that debugging becomes a simpler task.
|
||||
|
||||
There are a few available Loggers included with Swift Mailer, but writing your
|
||||
own implementation is incredibly simple and is achieved by creating a short
|
||||
class that implements the ``Swift_Plugins_Logger`` interface.
|
||||
|
||||
* ``Swift_Plugins_Loggers_ArrayLogger``: Keeps a collection of log messages
|
||||
inside an array. The array content can be cleared or dumped out to the
|
||||
screen.
|
||||
|
||||
* ``Swift_Plugins_Loggers_EchoLogger``: Prints output to the screen in
|
||||
realtime. Handy for very rudimentary debug output.
|
||||
|
||||
Using the Logger Plugin
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Logger Plugin -- like all plugins -- is added with the Mailer class'
|
||||
``registerPlugin()`` method. It accepts an instance of ``Swift_Plugins_Logger``
|
||||
in its constructor.
|
||||
|
||||
To use the Logger plugin:
|
||||
|
||||
* Create an instance of the Mailer using any Transport you choose.
|
||||
|
||||
* Create an instance of the a Logger implementation of
|
||||
``Swift_Plugins_Logger``.
|
||||
|
||||
* Create an instance of the ``Swift_Plugins_LoggerPlugin`` class, passing the
|
||||
created Logger instance to its constructor.
|
||||
|
||||
* Register the plugin using the Mailer's ``registerPlugin()`` method.
|
||||
|
||||
* Continue using Swift Mailer to send messages as normal.
|
||||
|
||||
* Dump the contents of the log with the logger's ``dump()`` method.
|
||||
|
||||
When Swift Mailer sends messages it will keep a log of all the interactions
|
||||
with the underlying Transport being used. Depending upon the Logger that has
|
||||
been used the behaviour will differ, but all implementations offer a way to
|
||||
get the contents of the log.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once 'lib/swift_required.php';
|
||||
|
||||
// Create the Mailer using any Transport
|
||||
$mailer = Swift_Mailer::newInstance(
|
||||
Swift_SmtpTransport::newInstance('smtp.example.org', 25)
|
||||
);
|
||||
|
||||
// To use the ArrayLogger
|
||||
$logger = new Swift_Plugins_Loggers_ArrayLogger();
|
||||
$mailer->registerPlugin(new Swift_Plugins_LoggerPlugin($logger));
|
||||
|
||||
// Or to use the Echo Logger
|
||||
$logger = new Swift_Plugins_Loggers_EchoLogger();
|
||||
$mailer->registerPlugin(new Swift_Plugins_LoggerPlugin($logger));
|
||||
|
||||
// Continue sending as normal
|
||||
for ($lotsOfRecipients as $recipient) {
|
||||
...
|
||||
|
||||
$mailer->send( ... );
|
||||
}
|
||||
|
||||
// Dump the log contents
|
||||
// NOTE: The EchoLogger dumps in realtime so dump() does nothing for it
|
||||
echo $logger->dump();
|
||||
|
||||
Decorator Plugin
|
||||
----------------
|
||||
|
||||
Often there's a need to send the same message to multiple recipients, but with
|
||||
tiny variations such as the recipient's name being used inside the message
|
||||
body. The Decorator plugin aims to provide a solution for allowing these small
|
||||
differences.
|
||||
|
||||
The decorator plugin works by intercepting the sending process of Swift
|
||||
Mailer, reading the email address in the To: field and then looking up a set
|
||||
of replacements for a template.
|
||||
|
||||
While the use of this plugin is simple, it is probably the most commonly
|
||||
misunderstood plugin due to the way in which it works. The typical mistake
|
||||
users make is to try registering the plugin multiple times (once for each
|
||||
recipient) -- inside a loop for example. This is incorrect.
|
||||
|
||||
The Decorator plugin should be registered just once, but containing the list
|
||||
of all recipients prior to sending. It will use this list of recipients to
|
||||
find the required replacements during sending.
|
||||
|
||||
Using the Decorator Plugin
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To use the Decorator plugin, simply create an associative array of replacements
|
||||
based on email addresses and then use the mailer's ``registerPlugin()`` method
|
||||
to add the plugin.
|
||||
|
||||
First create an associative array of replacements based on the email addresses
|
||||
you'll be sending the message to.
|
||||
|
||||
.. note::
|
||||
|
||||
The replacements array becomes a 2-dimensional array whose keys are the
|
||||
email addresses and whose values are an associative array of replacements
|
||||
for that email address. The curly braces used in this example can be any
|
||||
type of syntax you choose, provided they match the placeholders in your
|
||||
email template.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$replacements = array();
|
||||
foreach ($users as $user) {
|
||||
$replacements[$user['email']] = array(
|
||||
'{username}'=>$user['username'],
|
||||
'{password}'=>$user['password']
|
||||
);
|
||||
}
|
||||
|
||||
Now create an instance of the Decorator plugin using this array of replacements
|
||||
and then register it with the Mailer. Do this only once!
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$decorator = new Swift_Plugins_DecoratorPlugin($replacements);
|
||||
|
||||
$mailer->registerPlugin($decorator);
|
||||
|
||||
When you create your message, replace elements in the body (and/or the subject
|
||||
line) with your placeholders.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$message = Swift_Message::newInstance()
|
||||
->setSubject('Important notice for {username}')
|
||||
->setBody(
|
||||
"Hello {username}, we have reset your password to {password}\n" .
|
||||
"Please log in and change it at your earliest convenience."
|
||||
)
|
||||
;
|
||||
|
||||
foreach ($users as $user) {
|
||||
$message->addTo($user['email']);
|
||||
}
|
||||
|
||||
When you send this message to each of your recipients listed in your
|
||||
``$replacements`` array they will receive a message customized for just
|
||||
themselves. For example, the message used above when received may appear like
|
||||
this to one user:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Subject: Important notice for smilingsunshine2009
|
||||
|
||||
Hello smilingsunshine2009, we have reset your password to rainyDays
|
||||
Please log in and change it at your earliest convenience.
|
||||
|
||||
While another use may receive the message as:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Subject: Important notice for billy-bo-bob
|
||||
|
||||
Hello billy-bo-bob, we have reset your password to dancingOctopus
|
||||
Please log in and change it at your earliest convenience.
|
||||
|
||||
While the decorator plugin provides a means to solve this problem, there are
|
||||
various ways you could tackle this problem without the need for a plugin.
|
||||
We're trying to come up with a better way ourselves and while we have several
|
||||
(obvious) ideas we don't quite have the perfect solution to go ahead and
|
||||
implement it. Watch this space.
|
||||
|
||||
Providing Your Own Replacements Lookup for the Decorator
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Filling an array with replacements may not be the best solution for providing
|
||||
replacement information to the decorator. If you have a more elegant algorithm
|
||||
that performs replacement lookups on-the-fly you may provide your own
|
||||
implementation.
|
||||
|
||||
Providing your own replacements lookup implementation for the Decorator is
|
||||
simply a matter of passing an instance of ``Swift_Plugins_Decorator_Replacements`` to the decorator plugin's constructor,
|
||||
rather than passing in an array.
|
||||
|
||||
The Replacements interface is very simple to implement since it has just one
|
||||
method: ``getReplacementsFor($address)``.
|
||||
|
||||
Imagine you want to look up replacements from a database on-the-fly, you might
|
||||
provide an implementation that does this. You need to create a small class.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class DbReplacements implements Swift_Plugins_Decorator_Replacements {
|
||||
public function getReplacementsFor($address) {
|
||||
global $db; // Your PDO instance with a connection to your database
|
||||
$query = $db->prepare(
|
||||
"SELECT * FROM `users` WHERE `email` = ?"
|
||||
);
|
||||
|
||||
$query->execute([$address]);
|
||||
|
||||
if ($row = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||
return array(
|
||||
'{username}'=>$row['username'],
|
||||
'{password}'=>$row['password']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Now all you need to do is pass an instance of your class into the Decorator
|
||||
plugin's constructor instead of passing an array.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$decorator = new Swift_Plugins_DecoratorPlugin(new DbReplacements());
|
||||
|
||||
$mailer->registerPlugin($decorator);
|
||||
|
||||
For each message sent, the plugin will call your class' ``getReplacementsFor()``
|
||||
method to find the array of replacements it needs.
|
||||
|
||||
.. note::
|
||||
|
||||
If your lookup algorithm is case sensitive, you should transform the
|
||||
``$address`` argument as appropriate -- for example by passing it
|
||||
through ``strtolower()``.
|
||||
@@ -1,571 +0,0 @@
|
||||
Sending Messages
|
||||
================
|
||||
|
||||
Quick Reference for Sending a Message
|
||||
-------------------------------------
|
||||
|
||||
Sending a message is very straightforward. You create a Transport, use it to
|
||||
create the Mailer, then you use the Mailer to send the message.
|
||||
|
||||
To send a Message:
|
||||
|
||||
* Create a Transport from one of the provided Transports --
|
||||
``Swift_SmtpTransport``, ``Swift_SendmailTransport``
|
||||
or one of the aggregate Transports.
|
||||
|
||||
* Create an instance of the ``Swift_Mailer`` class, using the Transport as
|
||||
it's constructor parameter.
|
||||
|
||||
* Create a Message.
|
||||
|
||||
* Send the message via the ``send()`` method on the Mailer object.
|
||||
|
||||
.. caution::
|
||||
|
||||
The ``Swift_SmtpTransport`` and ``Swift_SendmailTransport`` transports use
|
||||
``proc_*`` PHP functions, which might not be available on your PHP
|
||||
installation. You can easily check if that's the case by running the
|
||||
following PHP script: ``<?php echo function_exists('proc_open') ? "Yep,
|
||||
that will work" : "Sorry, that won't work";``
|
||||
|
||||
When using ``send()`` the message will be sent just like it would be sent if you
|
||||
used your mail client. An integer is returned which includes the number of
|
||||
successful recipients. If none of the recipients could be sent to then zero will
|
||||
be returned, which equates to a boolean ``false``. If you set two ``To:``
|
||||
recipients and three ``Bcc:`` recipients in the message and all of the
|
||||
recipients are delivered to successfully then the value 5 will be returned.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once 'lib/swift_required.php';
|
||||
|
||||
// Create the Transport
|
||||
$transport = Swift_SmtpTransport::newInstance('smtp.example.org', 25)
|
||||
->setUsername('your username')
|
||||
->setPassword('your password')
|
||||
;
|
||||
|
||||
/*
|
||||
You could alternatively use a different transport such as Sendmail:
|
||||
|
||||
// Sendmail
|
||||
$transport = Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs');
|
||||
*/
|
||||
|
||||
// Create the Mailer using your created Transport
|
||||
$mailer = Swift_Mailer::newInstance($transport);
|
||||
|
||||
// Create a message
|
||||
$message = Swift_Message::newInstance('Wonderful Subject')
|
||||
->setFrom(array('john@doe.com' => 'John Doe'))
|
||||
->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
|
||||
->setBody('Here is the message itself')
|
||||
;
|
||||
|
||||
// Send the message
|
||||
$result = $mailer->send($message);
|
||||
|
||||
Transport Types
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
A Transport is the component which actually does the sending. You need to
|
||||
provide a Transport object to the Mailer class and there are several possible
|
||||
options.
|
||||
|
||||
Typically you will not need to know how a Transport works under-the-surface,
|
||||
you will only need to know how to create an instance of one, and which one to
|
||||
use for your environment.
|
||||
|
||||
The SMTP Transport
|
||||
..................
|
||||
|
||||
The SMTP Transport sends messages over the (standardized) Simple Message
|
||||
Transfer Protocol. It can deal with encryption and authentication.
|
||||
|
||||
The SMTP Transport, ``Swift_SmtpTransport`` is without doubt the most commonly
|
||||
used Transport because it will work on 99% of web servers (I just made that
|
||||
number up, but you get the idea). All the server needs is the ability to
|
||||
connect to a remote (or even local) SMTP server on the correct port number
|
||||
(usually 25).
|
||||
|
||||
SMTP servers often require users to authenticate with a username and password
|
||||
before any mail can be sent to other domains. This is easily achieved using
|
||||
Swift Mailer with the SMTP Transport.
|
||||
|
||||
SMTP is a protocol -- in other words it's a "way" of communicating a job
|
||||
to be done (i.e. sending a message). The SMTP protocol is the fundamental
|
||||
basis on which messages are delivered all over the internet 7 days a week, 365
|
||||
days a year. For this reason it's the most "direct" method of sending messages
|
||||
you can use and it's the one that will give you the most power and feedback
|
||||
(such as delivery failures) when using Swift Mailer.
|
||||
|
||||
Because SMTP is generally run as a remote service (i.e. you connect to it over
|
||||
the network/internet) it's extremely portable from server-to-server. You can
|
||||
easily store the SMTP server address and port number in a configuration file
|
||||
within your application and adjust the settings accordingly if the code is
|
||||
moved or if the SMTP server is changed.
|
||||
|
||||
Some SMTP servers -- Google for example -- use encryption for security reasons.
|
||||
Swift Mailer supports using both SSL and TLS encryption settings.
|
||||
|
||||
Using the SMTP Transport
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The SMTP Transport is easy to use. Most configuration options can be set with
|
||||
the constructor.
|
||||
|
||||
To use the SMTP Transport you need to know which SMTP server your code needs
|
||||
to connect to. Ask your web host if you're not sure. Lots of people ask me who
|
||||
to connect to -- I really can't answer that since it's a setting that's
|
||||
extremely specific to your hosting environment.
|
||||
|
||||
To use the SMTP Transport:
|
||||
|
||||
* Call ``Swift_SmtpTransport::newInstance()`` with the SMTP server name and
|
||||
optionally with a port number (defaults to 25).
|
||||
|
||||
* Use the returned object to create the Mailer.
|
||||
|
||||
A connection to the SMTP server will be established upon the first call to
|
||||
``send()``.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once 'lib/swift_required.php';
|
||||
|
||||
// Create the Transport
|
||||
$transport = Swift_SmtpTransport::newInstance('smtp.example.org', 25);
|
||||
|
||||
// Create the Mailer using your created Transport
|
||||
$mailer = Swift_Mailer::newInstance($transport);
|
||||
|
||||
/*
|
||||
It's also possible to use multiple method calls
|
||||
|
||||
$transport = Swift_SmtpTransport::newInstance()
|
||||
->setHost('smtp.example.org')
|
||||
->setPort(25)
|
||||
;
|
||||
*/
|
||||
|
||||
Encrypted SMTP
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
You can use SSL or TLS encryption with the SMTP Transport by specifying it as
|
||||
a parameter or with a method call.
|
||||
|
||||
To use encryption with the SMTP Transport:
|
||||
|
||||
* Pass the encryption setting as a third parameter to
|
||||
``Swift_SmtpTransport::newInstance()``; or
|
||||
|
||||
* Call the ``setEncryption()`` method on the Transport.
|
||||
|
||||
A connection to the SMTP server will be established upon the first call to
|
||||
``send()``. The connection will be initiated with the correct encryption
|
||||
settings.
|
||||
|
||||
.. note::
|
||||
|
||||
For SSL or TLS encryption to work your PHP installation must have
|
||||
appropriate OpenSSL transports wrappers. You can check if "tls" and/or
|
||||
"ssl" are present in your PHP installation by using the PHP function
|
||||
``stream_get_transports()``
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once 'lib/swift_required.php';
|
||||
|
||||
// Create the Transport
|
||||
$transport = Swift_SmtpTransport::newInstance('smtp.example.org', 587, 'ssl');
|
||||
|
||||
// Create the Mailer using your created Transport
|
||||
$mailer = Swift_Mailer::newInstance($transport);
|
||||
|
||||
/*
|
||||
It's also possible to use multiple method calls
|
||||
|
||||
$transport = Swift_SmtpTransport::newInstance()
|
||||
->setHost('smtp.example.org')
|
||||
->setPort(587)
|
||||
->setEncryption('ssl')
|
||||
;
|
||||
*/
|
||||
|
||||
SMTP with a Username and Password
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Some servers require authentication. You can provide a username and password
|
||||
with ``setUsername()`` and ``setPassword()`` methods.
|
||||
|
||||
To use a username and password with the SMTP Transport:
|
||||
|
||||
* Create the Transport with ``Swift_SmtpTransport::newInstance()``.
|
||||
|
||||
* Call the ``setUsername()`` and ``setPassword()`` methods on the Transport.
|
||||
|
||||
Your username and password will be used to authenticate upon first connect
|
||||
when ``send()`` are first used on the Mailer.
|
||||
|
||||
If authentication fails, an Exception of type ``Swift_TransportException`` will
|
||||
be thrown.
|
||||
|
||||
.. note::
|
||||
|
||||
If you need to know early whether or not authentication has failed and an
|
||||
Exception is going to be thrown, call the ``start()`` method on the
|
||||
created Transport.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once 'lib/swift_required.php';
|
||||
|
||||
// Create the Transport the call setUsername() and setPassword()
|
||||
$transport = Swift_SmtpTransport::newInstance('smtp.example.org', 25)
|
||||
->setUsername('username')
|
||||
->setPassword('password')
|
||||
;
|
||||
|
||||
// Create the Mailer using your created Transport
|
||||
$mailer = Swift_Mailer::newInstance($transport);
|
||||
|
||||
The Sendmail Transport
|
||||
......................
|
||||
|
||||
The Sendmail Transport sends messages by communicating with a locally
|
||||
installed MTA -- such as ``sendmail``.
|
||||
|
||||
The Sendmail Transport, ``Swift_SendmailTransport`` does not directly connect to
|
||||
any remote services. It is designed for Linux servers that have ``sendmail``
|
||||
installed. The Transport starts a local ``sendmail`` process and sends messages
|
||||
to it. Usually the ``sendmail`` process will respond quickly as it spools your
|
||||
messages to disk before sending them.
|
||||
|
||||
The Transport is named the Sendmail Transport for historical reasons
|
||||
(``sendmail`` was the "standard" UNIX tool for sending e-mail for years). It
|
||||
will send messages using other transfer agents such as Exim or Postfix despite
|
||||
its name, provided they have the relevant sendmail wrappers so that they can be
|
||||
started with the correct command-line flags.
|
||||
|
||||
It's a common misconception that because the Sendmail Transport returns a
|
||||
result very quickly it must therefore deliver messages to recipients quickly
|
||||
-- this is not true. It's not slow by any means, but it's certainly not
|
||||
faster than SMTP when it comes to getting messages to the intended recipients.
|
||||
This is because sendmail itself sends the messages over SMTP once they have
|
||||
been quickly spooled to disk.
|
||||
|
||||
The Sendmail Transport has the potential to be just as smart of the SMTP
|
||||
Transport when it comes to notifying Swift Mailer about which recipients were
|
||||
rejected, but in reality the majority of locally installed ``sendmail``
|
||||
instances are not configured well enough to provide any useful feedback. As such
|
||||
Swift Mailer may report successful deliveries where they did in fact fail before
|
||||
they even left your server.
|
||||
|
||||
You can run the Sendmail Transport in two different modes specified by command
|
||||
line flags:
|
||||
|
||||
* "``-bs``" runs in SMTP mode so theoretically it will act like the SMTP
|
||||
Transport
|
||||
|
||||
* "``-t``" runs in piped mode with no feedback, but theoretically faster,
|
||||
though not advised
|
||||
|
||||
You can think of the Sendmail Transport as a sort of asynchronous SMTP Transport
|
||||
-- though if you have problems with delivery failures you should try using the
|
||||
SMTP Transport instead. Swift Mailer isn't doing the work here, it's simply
|
||||
passing the work to somebody else (i.e. ``sendmail``).
|
||||
|
||||
Using the Sendmail Transport
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To use the Sendmail Transport you simply need to call
|
||||
``Swift_SendmailTransport::newInstance()`` with the command as a parameter.
|
||||
|
||||
To use the Sendmail Transport you need to know where ``sendmail`` or another MTA
|
||||
exists on the server. Swift Mailer uses a default value of
|
||||
``/usr/sbin/sendmail``, which should work on most systems.
|
||||
|
||||
You specify the entire command as a parameter (i.e. including the command line
|
||||
flags). Swift Mailer supports operational modes of "``-bs``" (default) and
|
||||
"``-t``".
|
||||
|
||||
.. note::
|
||||
|
||||
If you run sendmail in "``-t``" mode you will get no feedback as to whether
|
||||
or not sending has succeeded. Use "``-bs``" unless you have a reason not to.
|
||||
|
||||
To use the Sendmail Transport:
|
||||
|
||||
* Call ``Swift_SendmailTransport::newInstance()`` with the command, including
|
||||
the correct command line flags. The default is to use ``/usr/sbin/sendmail
|
||||
-bs`` if this is not specified.
|
||||
|
||||
* Use the returned object to create the Mailer.
|
||||
|
||||
A sendmail process will be started upon the first call to ``send()``. If the
|
||||
process cannot be started successfully an Exception of type
|
||||
``Swift_TransportException`` will be thrown.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once 'lib/swift_required.php';
|
||||
|
||||
// Create the Transport
|
||||
$transport = Swift_SendmailTransport::newInstance('/usr/sbin/exim -bs');
|
||||
|
||||
// Create the Mailer using your created Transport
|
||||
$mailer = Swift_Mailer::newInstance($transport);
|
||||
|
||||
The Mail Transport
|
||||
..................
|
||||
|
||||
The Mail Transport sends messages by delegating to PHP's internal
|
||||
``mail()`` function.
|
||||
|
||||
In my experience -- and others' -- the ``mail()`` function is not particularly
|
||||
predictable, or helpful.
|
||||
|
||||
Quite notably, the ``mail()`` function behaves entirely differently between
|
||||
Linux and Windows servers. On linux it uses ``sendmail``, but on Windows it uses
|
||||
SMTP.
|
||||
|
||||
In order for the ``mail()`` function to even work at all ``php.ini`` needs to be
|
||||
configured correctly, specifying the location of sendmail or of an SMTP server.
|
||||
|
||||
The problem with ``mail()`` is that it "tries" to simplify things to the point
|
||||
that it actually makes things more complex due to poor interface design. The
|
||||
developers of Swift Mailer have gone to a lot of effort to make the Mail
|
||||
Transport work with a reasonable degree of consistency.
|
||||
|
||||
Serious drawbacks when using this Transport are:
|
||||
|
||||
* Unpredictable message headers
|
||||
|
||||
* Lack of feedback regarding delivery failures
|
||||
|
||||
* Lack of support for several plugins that require real-time delivery feedback
|
||||
|
||||
It's a last resort, and we say that with a passion!
|
||||
|
||||
Available Methods for Sending Messages
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Mailer class offers two methods for sending Messages -- ``send()``.
|
||||
Each behaves in a slightly different way.
|
||||
|
||||
When a message is sent in Swift Mailer, the Mailer class communicates with
|
||||
whichever Transport class you have chosen to use.
|
||||
|
||||
Each recipient in the message should either be accepted or rejected by the
|
||||
Transport. For example, if the domain name on the email address is not
|
||||
reachable the SMTP Transport may reject the address because it cannot process
|
||||
it. Whichever method you use -- ``send()`` -- Swift Mailer will return
|
||||
an integer indicating the number of accepted recipients.
|
||||
|
||||
.. note::
|
||||
|
||||
It's possible to find out which recipients were rejected -- we'll cover that
|
||||
later in this chapter.
|
||||
|
||||
Using the ``send()`` Method
|
||||
...........................
|
||||
|
||||
The ``send()`` method of the ``Swift_Mailer`` class sends a message using
|
||||
exactly the same logic as your Desktop mail client would use. Just pass it a
|
||||
Message and get a result.
|
||||
|
||||
To send a Message with ``send()``:
|
||||
|
||||
* Create a Transport from one of the provided Transports --
|
||||
``Swift_SmtpTransport``, ``Swift_SendmailTransport``,
|
||||
or one of the aggregate Transports.
|
||||
|
||||
* Create an instance of the ``Swift_Mailer`` class, using the Transport as
|
||||
it's constructor parameter.
|
||||
|
||||
* Create a Message.
|
||||
|
||||
* Send the message via the ``send()`` method on the Mailer object.
|
||||
|
||||
The message will be sent just like it would be sent if you used your mail
|
||||
client. An integer is returned which includes the number of successful
|
||||
recipients. If none of the recipients could be sent to then zero will be
|
||||
returned, which equates to a boolean ``false``. If you set two
|
||||
``To:`` recipients and three ``Bcc:`` recipients in the message and all of the
|
||||
recipients are delivered to successfully then the value 5 will be returned.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once 'lib/swift_required.php';
|
||||
|
||||
// Create the Transport
|
||||
$transport = Swift_SmtpTransport::newInstance('localhost', 25);
|
||||
|
||||
// Create the Mailer using your created Transport
|
||||
$mailer = Swift_Mailer::newInstance($transport);
|
||||
|
||||
// Create a message
|
||||
$message = Swift_Message::newInstance('Wonderful Subject')
|
||||
->setFrom(array('john@doe.com' => 'John Doe'))
|
||||
->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
|
||||
->setBody('Here is the message itself')
|
||||
;
|
||||
|
||||
// Send the message
|
||||
$numSent = $mailer->send($message);
|
||||
|
||||
printf("Sent %d messages\n", $numSent);
|
||||
|
||||
/* Note that often that only the boolean equivalent of the
|
||||
return value is of concern (zero indicates FALSE)
|
||||
|
||||
if ($mailer->send($message))
|
||||
{
|
||||
echo "Sent\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Failed\n";
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
Sending Emails in Batch
|
||||
.......................
|
||||
|
||||
If you want to send a separate message to each recipient so that only their
|
||||
own address shows up in the ``To:`` field, follow the following recipe:
|
||||
|
||||
* Create a Transport from one of the provided Transports --
|
||||
``Swift_SmtpTransport``, ``Swift_SendmailTransport``,
|
||||
or one of the aggregate Transports.
|
||||
|
||||
* Create an instance of the ``Swift_Mailer`` class, using the Transport as
|
||||
it's constructor parameter.
|
||||
|
||||
* Create a Message.
|
||||
|
||||
* Iterate over the recipients and send message via the ``send()`` method on
|
||||
the Mailer object.
|
||||
|
||||
Each recipient of the messages receives a different copy with only their own
|
||||
email address on the ``To:`` field.
|
||||
|
||||
Make sure to add only valid email addresses as recipients. If you try to add an
|
||||
invalid email address with ``setTo()``, ``setCc()`` or ``setBcc()``, Swift
|
||||
Mailer will throw a ``Swift_RfcComplianceException``.
|
||||
|
||||
If you add recipients automatically based on a data source that may contain
|
||||
invalid email addresses, you can prevent possible exceptions by validating the
|
||||
addresses using ``Swift_Validate::email($email)`` and only adding addresses
|
||||
that validate. Another way would be to wrap your ``setTo()``, ``setCc()`` and
|
||||
``setBcc()`` calls in a try-catch block and handle the
|
||||
``Swift_RfcComplianceException`` in the catch block.
|
||||
|
||||
Handling invalid addresses properly is especially important when sending emails
|
||||
in large batches since a single invalid address might cause an unhandled
|
||||
exception and stop the execution or your script early.
|
||||
|
||||
.. note::
|
||||
|
||||
In the following example, two emails are sent. One to each of
|
||||
``receiver@domain.org`` and ``other@domain.org``. These recipients will
|
||||
not be aware of each other.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once 'lib/swift_required.php';
|
||||
|
||||
// Create the Transport
|
||||
$transport = Swift_SmtpTransport::newInstance('localhost', 25);
|
||||
|
||||
// Create the Mailer using your created Transport
|
||||
$mailer = Swift_Mailer::newInstance($transport);
|
||||
|
||||
// Create a message
|
||||
$message = Swift_Message::newInstance('Wonderful Subject')
|
||||
->setFrom(array('john@doe.com' => 'John Doe'))
|
||||
->setBody('Here is the message itself')
|
||||
;
|
||||
|
||||
// Send the message
|
||||
$failedRecipients = array();
|
||||
$numSent = 0;
|
||||
$to = array('receiver@domain.org', 'other@domain.org' => 'A name');
|
||||
|
||||
foreach ($to as $address => $name)
|
||||
{
|
||||
if (is_int($address)) {
|
||||
$message->setTo($name);
|
||||
} else {
|
||||
$message->setTo(array($address => $name));
|
||||
}
|
||||
|
||||
$numSent += $mailer->send($message, $failedRecipients);
|
||||
}
|
||||
|
||||
printf("Sent %d messages\n", $numSent);
|
||||
|
||||
Finding out Rejected Addresses
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It's possible to get a list of addresses that were rejected by the Transport
|
||||
by using a by-reference parameter to ``send()``.
|
||||
|
||||
As Swift Mailer attempts to send the message to each address given to it, if a
|
||||
recipient is rejected it will be added to the array. You can pass an existing
|
||||
array, otherwise one will be created by-reference.
|
||||
|
||||
Collecting the list of recipients that were rejected can be useful in
|
||||
circumstances where you need to "prune" a mailing list for example when some
|
||||
addresses cannot be delivered to.
|
||||
|
||||
Getting Failures By-reference
|
||||
.............................
|
||||
|
||||
Collecting delivery failures by-reference with the ``send()`` method is as
|
||||
simple as passing a variable name to the method call.
|
||||
|
||||
To get failed recipients by-reference:
|
||||
|
||||
* Pass a by-reference variable name to the ``send()`` method of the Mailer
|
||||
class.
|
||||
|
||||
If the Transport rejects any of the recipients, the culprit addresses will be
|
||||
added to the array provided by-reference.
|
||||
|
||||
.. note::
|
||||
|
||||
If the variable name does not yet exist, it will be initialized as an
|
||||
empty array and then failures will be added to that array. If the variable
|
||||
already exists it will be type-cast to an array and failures will be added
|
||||
to it.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mailer = Swift_Mailer::newInstance( ... );
|
||||
|
||||
$message = Swift_Message::newInstance( ... )
|
||||
->setFrom( ... )
|
||||
->setTo(array(
|
||||
'receiver@bad-domain.org' => 'Receiver Name',
|
||||
'other@domain.org' => 'A name',
|
||||
'other-receiver@bad-domain.org' => 'Other Name'
|
||||
))
|
||||
->setBody( ... )
|
||||
;
|
||||
|
||||
// Pass a variable name to the send() method
|
||||
if (!$mailer->send($message, $failures))
|
||||
{
|
||||
echo "Failures:";
|
||||
print_r($failures);
|
||||
}
|
||||
|
||||
/*
|
||||
Failures:
|
||||
Array (
|
||||
0 => receiver@bad-domain.org,
|
||||
1 => other-receiver@bad-domain.org
|
||||
)
|
||||
*/
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,62 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A binary safe string comparison.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class IdenticalBinaryConstraint extends \PHPUnit_Framework_Constraint
|
||||
{
|
||||
protected $value;
|
||||
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the constraint for parameter $other. Returns TRUE if the
|
||||
* constraint is met, FALSE otherwise.
|
||||
*
|
||||
* @param mixed $other Value or object to evaluate.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function matches($other)
|
||||
{
|
||||
$aHex = $this->asHexString($this->value);
|
||||
$bHex = $this->asHexString($other);
|
||||
|
||||
return $aHex === $bHex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the constraint.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toString()
|
||||
{
|
||||
return 'indentical binary';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the given string of bytes as a stirng of Hexadecimal sequences.
|
||||
*
|
||||
* @param string $binary
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function asHexString($binary)
|
||||
{
|
||||
$hex = '';
|
||||
|
||||
$bytes = unpack('H*', $binary);
|
||||
|
||||
foreach ($bytes as &$byte) {
|
||||
$byte = strtoupper($byte);
|
||||
}
|
||||
|
||||
return implode('', $bytes);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_StreamCollector
|
||||
{
|
||||
public $content = '';
|
||||
|
||||
public function __invoke($arg)
|
||||
{
|
||||
$this->content .= $arg;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Base test for smoke tests.
|
||||
*
|
||||
* @author Rouven Weßling
|
||||
*/
|
||||
class SwiftMailerSmokeTestCase extends SwiftMailerTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
if (!defined('SWIFT_SMOKE_TRANSPORT_TYPE')) {
|
||||
$this->markTestSkipped(
|
||||
'Smoke tests are skipped if tests/smoke.conf.php is not edited'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function _getMailer()
|
||||
{
|
||||
switch (SWIFT_SMOKE_TRANSPORT_TYPE) {
|
||||
case 'smtp':
|
||||
$transport = Swift_DependencyContainer::getInstance()->lookup('transport.smtp')
|
||||
->setHost(SWIFT_SMOKE_SMTP_HOST)
|
||||
->setPort(SWIFT_SMOKE_SMTP_PORT)
|
||||
->setUsername(SWIFT_SMOKE_SMTP_USER)
|
||||
->setPassword(SWIFT_SMOKE_SMTP_PASS)
|
||||
->setEncryption(SWIFT_SMOKE_SMTP_ENCRYPTION)
|
||||
;
|
||||
break;
|
||||
case 'sendmail':
|
||||
$transport = Swift_DependencyContainer::getInstance()->lookup('transport.sendmail')
|
||||
->setCommand(SWIFT_SMOKE_SENDMAIL_COMMAND)
|
||||
;
|
||||
break;
|
||||
case 'mail':
|
||||
case 'nativemail':
|
||||
$transport = Swift_DependencyContainer::getInstance()->lookup('transport.mail');
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Undefined transport ['.SWIFT_SMOKE_TRANSPORT_TYPE.']');
|
||||
}
|
||||
|
||||
return new Swift_Mailer($transport);
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A base test case with some custom expectations.
|
||||
*
|
||||
* @author Rouven Weßling
|
||||
*/
|
||||
class SwiftMailerTestCase extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public static function regExp($pattern)
|
||||
{
|
||||
if (!is_string($pattern)) {
|
||||
throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
|
||||
}
|
||||
|
||||
return new PHPUnit_Framework_Constraint_PCREMatch($pattern);
|
||||
}
|
||||
|
||||
public function assertIdenticalBinary($expected, $actual, $message = '')
|
||||
{
|
||||
$constraint = new IdenticalBinaryConstraint($expected);
|
||||
self::assertThat($actual, $constraint, $message);
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
\Mockery::close();
|
||||
}
|
||||
|
||||
protected function getMockery($class)
|
||||
{
|
||||
return \Mockery::mock($class);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
ISO-2022-JPは、インターネット上(特に電子メール)などで使われる日本の文字用の文字符号化方式。ISO/IEC 2022のエスケープシーケンスを利用して文字集合を切り替える7ビットのコードであることを特徴とする (アナウンス機能のエスケープシーケンスは省略される)。俗に「JISコード」と呼ばれることもある。
|
||||
|
||||
概要
|
||||
日本語表記への利用が想定されている文字コードであり、日本語の利用されるネットワークにおいて、日本の規格を応用したものである。また文字集合としては、日本語で用いられる漢字、ひらがな、カタカナはもちろん、ラテン文字、ギリシア文字、キリル文字なども含んでおり、学術や産業の分野での利用も考慮たものとなっている。規格名に、ISOの日本語の言語コードであるjaではなく、国・地域名コードのJPが示されているゆえんである。
|
||||
文字集合としてJIS X 0201のC0集合(制御文字)、JIS X 0201のラテン文字集合、ISO 646の国際基準版図形文字、JIS X 0208の1978年版(JIS C 6226-1978)と1983年および1990年版が利用できる。JIS X 0201の片仮名文字集合は利用できない。1986年以降、日本の電子メールで用いられてきたJUNETコードを、村井純・Mark Crispin・Erik van der Poelが1993年にRFC化したもの(RFC 1468)。後にJIS X 0208:1997の附属書2としてJISに規定された。MIMEにおける文字符号化方式の識別用の名前として IANA に登録されている。
|
||||
なお、符号化の仕様についてはISO/IEC 2022#ISO-2022-JPも参照。
|
||||
|
||||
ISO-2022-JPと非標準的拡張使用
|
||||
「JISコード」(または「ISO-2022-JP」)というコード名の規定下では、その仕様通りの使用が求められる。しかし、Windows OS上では、実際にはCP932コード (MicrosoftによるShift JISを拡張した亜種。ISO-2022-JP規定外文字が追加されている。)による独自拡張(の文字)を断りなく使うアプリケーションが多い。この例としてInternet ExplorerやOutlook Expressがある。また、EmEditor、秀丸エディタやThunderbirdのようなMicrosoft社以外のWindowsアプリケーションでも同様の場合がある。この場合、ISO-2022-JPの範囲外の文字を使ってしまうと、異なる製品間では未定義不明文字として認識されるか、もしくは文字化けを起こす原因となる。そのため、Windows用の電子メールクライアントであっても独自拡張の文字を使用すると警告を出したり、あえて使えないように制限しているものも存在する。さらにはISO-2022-JPの範囲内であってもCP932は非標準文字(FULLWIDTH TILDE等)を持つので文字化けの原因になり得る。
|
||||
また、符号化方式名をISO-2022-JPとしているのに、文字集合としてはJIS X 0212 (いわゆる補助漢字) やJIS X 0201の片仮名文字集合 (いわゆる半角カナ) をも符号化している例があるが、ISO-2022-JPではこれらの文字を許容していない。これらの符号化は独自拡張の実装であり、中にはISO/IEC 2022の仕様に準拠すらしていないものもある[2]。従って受信側の電子メールクライアントがこれらの独自拡張に対応していない場合、その文字あるいはその文字を含む行、時にはテキスト全体が文字化けすることがある。
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
Op mat eraus hinnen beschte, rou zënne schaddreg ké. Ké sin Eisen Kaffi prächteg, den haut esou Fielse wa, Well zielen d'Welt am dir. Aus grousse rëschten d'Stroos do, as dat Kléder gewëss d'Kàchen. Schied gehéiert d'Vioule net hu, rou ke zënter Säiten d'Hierz. Ze eise Fletschen mat, gei as gréng d'Lëtzebuerger. Wäit räich no mat.
|
||||
|
||||
Säiten d'Liewen aus en. Un gëtt bléit lossen wee, da wéi alle weisen Kolrettchen. Et deser d'Pan d'Kirmes vun, en wuel Benn rëschten méi. En get drem ménger beschte, da wär Stad welle. Nun Dach d'Pied do, mä gét ruffen gehéiert. Ze onser ugedon fir, d'Liewen Plett'len ech no, si Räis wielen bereet wat. Iwer spilt fir jo.
|
||||
|
||||
An hin däischter Margréitchen, eng ke Frot brommt, vu den Räis néierens. Da hir Hunn Frot nozegon, rout Fläiß Himmel zum si, net gutt Kaffi Gesträich fu. Vill lait Gaart sou wa, Land Mamm Schuebersonndeg rei do. Gei geet Minutt en, gei d'Leit beschte Kolrettchen et, Mamm fergiess un hun.
|
||||
|
||||
Et gutt Heck kommen oft, Lann rëscht rei um, Hunn rëscht schéinste ke der. En lait zielen schnéiwäiss hir, fu rou botze éiweg Minutt, rem fest gudden schaddreg en. Noper bereet Margréitchen mat op, dem denkt d'Leit d'Vioule no, oft ké Himmel Hämmel. En denkt blénken Fréijor net, Gart Schiet d'Natur no wou. No hin Ierd Frot d'Kirmes. Hire aremt un rou, ké den éiweg wielen Milliounen.
|
||||
|
||||
Mir si Hunn Blénkeg. Ké get ston derfir d'Kàchen. Haut d'Pan fu ons, dé frou löschteg d'Meereische rei. Sou op wuel Léift. Stret schlon grousse gin hu. Mä denkt d'Leit hinnen net, ké gét haut fort rëscht.
|
||||
|
||||
Koum d'Pan hannendrun ass ké, ké den brét Kaffi geplot. Schéi Hären d'Pied fu gét, do d'Mier néierens bei. Rëm päift Hämmel am, wee Engel beschéngt mä. Brommt klinzecht der ke, wa rout jeitzt dén. Get Zalot d'Vioule däischter da, jo fir Bänk päift duerch, bei d'Beem schéinen Plett'len jo. Den haut Faarwen ze, eng en Biereg Kirmesdag, um sin alles Faarwen d'Vioule.
|
||||
|
||||
Eng Hunn Schied et, wat wa Frot fest gebotzt. Bei jo bleiwe ruffen Klarinett. Un Feld klinzecht gét, rifft Margréitchen rem ke. Mir dé Noper duurch gewëss, ston sech kille sin en. Gei Stret d'Wise um, Haus Gart wee as. Monn ménger an blo, wat da Gart gefällt Hämmelsbrot.
|
||||
|
||||
Brommt geplot och ze, dat wa Räis Well Kaffi. Do get spilt prächteg, as wär kille bleiwe gewalteg. Onser frësch Margréitchen rem ke, blo en huet ugedon. Onser Hemecht wär de, hu eraus d'Sonn dat, eise deser hannendrun da och.
|
||||
|
||||
As durch Himmel hun, no fest iw'rem schéinste mir, Hunn séngt Hierz ke zum. Séngt iw'rem d'Natur zum an. Ke wär gutt Grénge. Kënnt gudden prächteg mä rei. Dé dir Blénkeg Klarinett Kolrettchen, da fort muerges d'Kanner wou, main Feld ruffen vu wéi. Da gin esou Zalot gewalteg, gét vill Hemecht blénken dé.
|
||||
|
||||
Haut gréng nun et, nei vu Bass gréng d'Gaassen. Fest d'Beem uechter si gin. Oft vu sinn wellen kréien. Et ass lait Zalot schéinen.
|
||||
@@ -1,22 +0,0 @@
|
||||
Код одно гринспана руководишь на. Его вы знания движение. Ты две начать
|
||||
одиночку, сказать основатель удовольствием но миф. Бы какие система тем.
|
||||
Полностью использует три мы, человек клоунов те нас, бы давать творческую
|
||||
эзотерическая шеф.
|
||||
|
||||
Мог не помнить никакого сэкономленного, две либо какие пишите бы. Должен
|
||||
компанию кто те, этот заключалась проектировщик не ты. Глупые периоды ты
|
||||
для. Вам который хороший он. Те любых кремния концентрируются мог,
|
||||
собирать принадлежите без вы.
|
||||
|
||||
Джоэла меньше хорошего вы миф, за тем году разработки. Даже управляющим
|
||||
руководители был не. Три коде выпускать заботиться ну. То его система
|
||||
удовольствием безостановочно, или ты главной процессорах. Мы без джоэл
|
||||
знания получат, статьи остальные мы ещё.
|
||||
|
||||
Них русском касается поскольку по, образование должником
|
||||
систематизированный ну мои. Прийти кандидата университет но нас, для бы
|
||||
должны никакого, биг многие причин интервьюирования за.
|
||||
|
||||
Тем до плиту почему. Вот учёт такие одного бы, об биг разным внешних
|
||||
промежуток. Вас до какому возможностей безответственный, были погодите бы
|
||||
его, по них глупые долгий количества.
|
||||
@@ -1,45 +0,0 @@
|
||||
Αν ήδη διάβασε γλιτώσει μεταγλωτίσει, αυτήν θυμάμαι μου μα. Την κατάσταση χρησιμοποίησέ να! Τα διαφορά φαινόμενο διολισθήσεις πες, υψηλότερη προκαλείς περισσότερες όχι κι. Με ελέγχου γίνεται σας, μικρής δημιουργούν τη του. Τις τα γράψει εικόνες απαράδεκτη?
|
||||
|
||||
Να ότι πρώτοι απαραίτητο. Άμεση πετάνε κακόκεφος τον ώς, να χώρου πιθανότητες του. Το μέχρι ορίστε λιγότερους σας. Πω ναί φυσικά εικόνες.
|
||||
|
||||
Μου οι κώδικα αποκλειστικούς, λες το μάλλον συνεχώς. Νέου σημεία απίστευτα σας μα. Χρόνου μεταγλωτιστής σε νέα, τη τις πιάνει μπορούσες προγραμματιστές. Των κάνε βγαίνει εντυπωσιακό τα? Κρατάει τεσσαρών δυστυχώς της κι, ήδη υψηλότερη εξακολουθεί τα?
|
||||
|
||||
Ώρα πετάνε μπορούσε λιγότερους αν, τα απαράδεκτη συγχωνευτεί ροή. Τη έγραψες συνηθίζουν σαν. Όλα με υλικό στήλες χειρότερα. Ανώδυνη δουλέψει επί ως, αν διαδίκτυο εσωτερικών παράγοντες από. Κεντρικό επιτυχία πες το.
|
||||
|
||||
Πω ναι λέει τελειώσει, έξι ως έργων τελειώσει. Με αρχεία βουτήξουν ανταγωνιστής ώρα, πολύ γραφικά σελίδων τα στη. Όρο οέλεγχος δημιουργούν δε, ας θέλεις ελέγχου συντακτικό όρο! Της θυμάμαι επιδιόρθωση τα. Για μπορούσε περισσότερο αν, μέγιστη σημαίνει αποφάσισε τα του, άτομο αποτελέσει τι στα.
|
||||
|
||||
Τι στην αφήσεις διοίκηση στη. Τα εσφαλμένη δημιουργια επιχείριση έξι! Βήμα μαγικά εκτελέσει ανά τη. Όλη αφήσεις συνεχώς εμπορικά αν, το λες κόλπα επιτυχία. Ότι οι ζώνη κειμένων. Όρο κι ρωτάει γραμμής πελάτες, τελειώσει διολισθήσεις καθυστερούσε αν εγώ? Τι πετούν διοίκηση προβλήματα ήδη.
|
||||
|
||||
Τη γλιτώσει αποθηκευτικού μια. Πω έξι δημιουργια πιθανότητες, ως πέντε ελέγχους εκτελείται λες. Πως ερωτήσεις διοικητικό συγκεντρωμένοι οι, ας συνεχώς διοικητικό αποστηθίσει σαν. Δε πρώτες συνεχώς διολισθήσεις έχω, από τι κανένας βουτήξουν, γειτονιάς προσεκτικά ανταγωνιστής κι σαν.
|
||||
|
||||
Δημιουργια συνηθίζουν κλπ τι? Όχι ποσοστό διακοπής κι. Κλπ φακέλους δεδομένη εξοργιστικά θα? Υποψήφιο καθορίζουν με όλη, στα πήρε προσοχή εταιρείες πω, ώς τον συνάδελφος διοικητικό δημιουργήσεις! Δούλευε επιτίθενται σας θα, με ένας παραγωγικής ένα, να ναι σημεία μέγιστη απαράδεκτη?
|
||||
|
||||
Σας τεσσαρών συνεντεύξης τη, αρπάζεις σίγουρος μη για', επί τοπικές εντολές ακούσει θα? Ως δυστυχής μεταγλωτιστής όλη, να την είχαν σφάλμα απαραίτητο! Μην ώς άτομο διορθώσει χρησιμοποιούνταν. Δεν τα κόλπα πετάξαμε, μη που άγχος υόρκη άμεση, αφού δυστυχώς διακόψουμε όρο αν! Όλη μαγικά πετάνε επιδιορθώσεις δε, ροή φυσικά αποτελέσει πω.
|
||||
|
||||
Άπειρα παραπάνω φαινόμενο πω ώρα, σαν πόρτες κρατήσουν συνηθίζουν ως. Κι ώρα τρέξει είχαμε εφαρμογή. Απλό σχεδιαστής μεταγλωτιστής ας επί, τις τα όταν έγραψες γραμμής? Όλα κάνεις συνάδελφος εργαζόμενοι θα, χαρτιού χαμηλός τα ροή. Ως ναι όροφο έρθει, μην πελάτες αποφάσισε μεταφραστής με, να βιαστικά εκδόσεις αναζήτησης λες. Των φταίει εκθέσεις προσπαθήσεις οι, σπίτι αποστηθίσει ας λες?
|
||||
|
||||
Ώς που υπηρεσία απαραίτητο δημιουργείς. Μη άρα χαρά καθώς νύχτας, πω ματ μπουν είχαν. Άμεση δημιουργείς ώς ροή, γράψει γραμμής σίγουρος στα τι! Αν αφού πρώτοι εργαζόμενων ναί.
|
||||
|
||||
Άμεση διορθώσεις με δύο? Έχουν παράδειγμα των θα, μου έρθει θυμάμαι περισσότερο το. Ότι θα αφού χρειάζονται περισσότερες. Σαν συνεχώς περίπου οι.
|
||||
|
||||
Ώς πρώτης πετάξαμε λες, όρο κι πρώτες ζητήσεις δυστυχής. Ανά χρόνου διακοπή επιχειρηματίες ας, ώς μόλις άτομο χειρότερα όρο, κρατάει σχεδιαστής προσπαθήσεις νέο το. Πουλάς προσθέσει όλη πω, τύπου χαρακτηριστικό εγώ σε, πω πιο δούλευε αναζήτησης? Αναφορά δίνοντας σαν μη, μάθε δεδομένη εσωτερικών με ναι, αναφέρονται περιβάλλοντος ώρα αν. Και λέει απόλαυσε τα, που το όροφο προσπαθούν?
|
||||
|
||||
Πάντα χρόνου χρήματα ναι το, σαν σωστά θυμάμαι σκεφτείς τα. Μα αποτελέσει ανεπιθύμητη την, πιο το τέτοιο ατόμου, τη των τρόπο εργαλείων επιδιόρθωσης. Περιβάλλον παραγωγικής σου κι, κλπ οι τύπου κακόκεφους αποστηθίσει, δε των πλέον τρόποι. Πιθανότητες χαρακτηριστικών σας κι, γραφικά δημιουργήσεις μια οι, πω πολλοί εξαρτάται προσεκτικά εδώ. Σταματάς παράγοντες για' ώς, στις ρωτάει το ναι! Καρέκλα ζητήσεις συνδυασμούς τη ήδη!
|
||||
|
||||
Για μαγικά συνεχώς ακούσει το. Σταματάς προϊόντα βουτήξουν ώς ροή. Είχαν πρώτες οι ναι, μα λες αποστηθίσει ανακαλύπτεις. Όροφο άλγεβρα παραπάνω εδώ τη, πρόσληψη λαμβάνουν καταλάθος ήδη ας? Ως και εισαγωγή κρατήσουν, ένας κακόκεφους κι μας, όχι κώδικάς παίξουν πω. Πω νέα κρατάει εκφράσουν, τότε τελικών τη όχι, ας της τρέξει αλλάζοντας αποκλειστικούς.
|
||||
|
||||
Ένας βιβλίο σε άρα, ναι ως γράψει ταξινομεί διορθώσεις! Εδώ να γεγονός συγγραφείς, ώς ήδη διακόψουμε επιχειρηματίες? Ότι πακέτων εσφαλμένη κι, θα όρο κόλπα παραγωγικής? Αν έχω κεντρικό υψηλότερη, κι δεν ίδιο πετάνε παρατηρούμενη! Που λοιπόν σημαντικό μα, προκαλείς χειροκροτήματα ως όλα, μα επί κόλπα άγχος γραμμές! Δε σου κάνεις βουτήξουν, μη έργων επενδυτής χρησιμοποίησέ στα, ως του πρώτες διάσημα σημαντικό.
|
||||
|
||||
Βιβλίο τεράστιο προκύπτουν σαν το, σαν τρόπο επιδιόρθωση ας. Είχαν προσοχή προσπάθεια κι ματ, εδώ ως έτσι σελίδων συζήτηση. Και στην βγαίνει εσφαλμένη με, δυστυχής παράδειγμα δε μας, από σε υόρκη επιδιόρθωσης. Νέα πω νέου πιθανό, στήλες συγγραφείς μπαίνοντας μα για', το ρωτήσει κακόκεφους της? Μου σε αρέσει συγγραφής συγχωνευτεί, μη μου υόρκη ξέχασε διακοπής! Ώς επί αποφάσισε αποκλειστικούς χρησιμοποιώντας, χρήματα σελίδων ταξινομεί ναι με.
|
||||
|
||||
Μη ανά γραμμή απόλαυσε, πω ναι μάτσο διασφαλίζεται. Τη έξι μόλις εργάστηκε δημιουργούν, έκδοση αναφορά δυσκολότερο οι νέο. Σας ως μπορούσε παράδειγμα, αν ότι δούλευε μπορούσε αποκλειστικούς, πιο λέει βουτήξουν διορθώσει ως. Έχω τελευταία κακόκεφους ας, όσο εργαζόμενων δημιουργήσεις τα.
|
||||
|
||||
Του αν δουλέψει μπορούσε, πετούν χαμηλός εδώ ας? Κύκλο τύπους με που, δεν σε έχουν συνεχώς χειρότερα, τις τι απαράδεκτη συνηθίζουν? Θα μην τους αυτήν, τη ένα πήρε πακέτων, κι προκύπτουν περιβάλλον πως. Μα για δουλέψει απόλαυσε εφαμοργής, ώς εδώ σημαίνει μπορούσες, άμεση ακούσει προσοχή τη εδώ?
|
||||
|
||||
Στα δώσε αθόρυβες λιγότερους οι, δε αναγκάζονται αποκλειστικούς όλα! Ας μπουν διοικητικό μια, πάντα ελέγχου διορθώσεις ώς τον. Ότι πήρε κανόνα μα. Που άτομα κάνεις δημιουργίες τα, οι μας αφού κόλπα προγραμματιστής, αφού ωραίο προκύπτουν στα ως. Θέμα χρησιμοποιήσει αν όλα, του τα άλγεβρα σελίδων. Τα ότι ανώδυνη δυστυχώς συνδυασμούς, μας οι πάντα γνωρίζουμε ανταγωνιστής, όχι τα δοκιμάσεις σχεδιαστής! Στην συνεντεύξης επιδιόρθωση πιο τα, μα από πουλάς περιβάλλον παραγωγικής.
|
||||
|
||||
Έχουν μεταγλωτίσει σε σας, σε πάντα πρώτης μειώσει των, γράψει ρουτίνα δυσκολότερο ήδη μα? Ταξινομεί διορθώσεις να μας. Θα της προσπαθούν περιεχόμενα, δε έχω τοπικές στέλνοντάς. Ανά δε αλφα άμεση, κάποιο ρωτάει γνωρίζουμε πω στη, φράση μαγικά συνέχεια δε δύο! Αν είχαμε μειώσει ροή, μας μετράει καθυστερούσε επιδιορθώσεις μη. Χάος υόρκη κεντρικό έχω σε, ανά περίπου αναγκάζονται πω.
|
||||
|
||||
Όσο επιστρέφουν χρονοδιαγράμματα μη. Πως ωραίο κακόκεφος διαχειριστής ως, τις να διακοπής αναζήτησης. Κάποιο ποσοστό ταξινομεί επί τη? Μάθε άμεση αλλάζοντας δύο με, μου νέου πάντα να.
|
||||
|
||||
Πω του δυστυχώς πιθανότητες. Κι ρωτάει υψηλότερη δημιουργια ότι, πω εισαγωγή τελευταία απομόνωση ναι. Των ζητήσεις γνωρίζουμε ώς? Για' μη παραδοτέου αναφέρονται! Ύψος παραγωγικά ροή ως, φυσικά διάβασε εικόνες όσο σε? Δεν υόρκη διορθώσεις επεξεργασία θα, ως μέση σύστημα χρησιμοποιήσει τις.
|
||||
@@ -1,3 +0,0 @@
|
||||
रखति आवश्यकत प्रेरना मुख्यतह हिंदी किएलोग असक्षम कार्यलय करते विवरण किके मानसिक दिनांक पुर्व संसाध एवम् कुशलता अमितकुमार प्रोत्साहित जनित देखने उदेशीत विकसित बलवान ब्रौशर किएलोग विश्लेषण लोगो कैसे जागरुक प्रव्रुति प्रोत्साहित सदस्य आवश्यकत प्रसारन उपलब्धता अथवा हिंदी जनित दर्शाता यन्त्रालय बलवान अतित सहयोग शुरुआत सभीकुछ माहितीवानीज्य लिये खरिदे है।अभी एकत्रित सम्पर्क रिती मुश्किल प्राथमिक भेदनक्षमता विश्व उन्हे गटको द्वारा तकरीबन
|
||||
|
||||
विश्व द्वारा व्याख्या सके। आजपर वातावरण व्याख्यान पहोच। हमारी कीसे प्राथमिक विचारशिलता पुर्व करती कम्प्युटर भेदनक्षमता लिये बलवान और्४५० यायेका वार्तालाप सुचना भारत शुरुआत लाभान्वित पढाए संस्था वर्णित मार्गदर्शन चुनने
|
||||
@@ -1,15 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQDZeUdi1RKnm9cRYNn6E24xxrRTouh3Va8JOEHQ5SB018lvbjwH
|
||||
2lW5mZ/I0kh/dHsTN0zcN0VE62WIbnLreMk/af/4Pg1i93+c9TmfXmoropsmdLos
|
||||
w0tjq50jGbBqtHZNJYAokP/u3uUuRw8g0V/O4zlQ3GlO/PDH7xDQzekl9wIDAQAB
|
||||
AoGAaoCBXD5a72hbb/BNb7HaUlgscZUjYWW93bcGTGYZef8/b+m9Tl83gjhgzvlk
|
||||
db62k1eOtX3/11uskp78eqLhctv7yWc0mQQhgOogY2qCwHTCH8wja8kJkUAnKQhs
|
||||
P9sa5iJvgckiuX3SdxgTMwib9d1VyGq6YywiORiZF9rxyhECQQD/xhiZSi7y0ciB
|
||||
g4bassy0GVMS7EDRumMHc8wC23E1H2mj5yPE/QLqkW4ddmCv2BbJnYmyNvOaK9tk
|
||||
T2W+mn3/AkEA2aqDGja9CaTlY4BCXfiT166n+xVl5+d+1DENQ4FK9O2jpSi1265J
|
||||
tjEkXVxUOpV1ZEcUVOdK6RpvsKpc7vVICQJBALEFO5UsQJ4SD0GD9Ft8kCy9sj9Q
|
||||
f/Qnmc5YmIQJuKpZmVW07Y6yxcfu61U8zuIlHnBftiM/4Q18+RTN1s86QaUCQHoL
|
||||
9MTfCnH85q46/XuJZQRbp07O+bvlfqTl+CTwuyHImaiCwi2ydRxWQ6ihm4zZvuAC
|
||||
RvEwWz2HGDc73y4RlFkCQDDdnN9e46l1nMDLDI4cyyGBVg4Z2IZ3IAu5GaoUCGjM
|
||||
a8w6kxE8f1d8DD5vvqVbmfK89TA/DjT+7/arBNBCiCM=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,6 +0,0 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZeUdi1RKnm9cRYNn6E24xxrRT
|
||||
ouh3Va8JOEHQ5SB018lvbjwH2lW5mZ/I0kh/dHsTN0zcN0VE62WIbnLreMk/af/4
|
||||
Pg1i93+c9TmfXmoropsmdLosw0tjq50jGbBqtHZNJYAokP/u3uUuRw8g0V/O4zlQ
|
||||
3GlO/PDH7xDQzekl9wIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -1 +0,0 @@
|
||||
<data>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
@@ -1 +0,0 @@
|
||||
D42DA34CF90FA0DE
|
||||
@@ -1,21 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDazCCAlOgAwIBAgIJAKJCGQYLxWT1MA0GCSqGSIb3DQEBBQUAMEwxFzAVBgNV
|
||||
BAMMDlN3aWZ0bWFpbGVyIENBMRQwEgYDVQQKDAtTd2lmdG1haWxlcjEOMAwGA1UE
|
||||
BwwFUGFyaXMxCzAJBgNVBAYTAkZSMB4XDTEzMTEyNzA4MzkxMFoXDTE3MTEyNjA4
|
||||
MzkxMFowTDEXMBUGA1UEAwwOU3dpZnRtYWlsZXIgQ0ExFDASBgNVBAoMC1N3aWZ0
|
||||
bWFpbGVyMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQC7RLdHE3OWo9aZwv1xA/cYyPui/gegxpTqClRp
|
||||
gGcVQ+jxIfnJQDQndyoAvFDiqOiZ+gAjZGJeUHDp9C/2IZp05MLh+omt9N8pBykm
|
||||
3nj/3ZwPXOAO0uyDPAOHhISITAxEuZCqDnq7iYujywtwfQ7bpW1hCK9PfNZYMStM
|
||||
kw7LsGr5BqcKkPuOWTvxE3+NqK8HxydYolsoApEGhgonyImVh1Pg1Kjkt5ojvwAX
|
||||
zOdjfw5poY5NArwuLORUH+XocetRo8DC6S42HkU/MoqcYxa9EuRuwuQh7GtE6baR
|
||||
PgrDsEYaY4Asy43sK81V51F/8Q1bHZKN/goQdxQwzv+/nOLTAgMBAAGjUDBOMB0G
|
||||
A1UdDgQWBBRHgqkl543tKhsVAvcx1I0JFU7JuDAfBgNVHSMEGDAWgBRHgqkl543t
|
||||
KhsVAvcx1I0JFU7JuDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAz
|
||||
OJiEQcygKGkkXXDiXGBvP/cSznj3nG9FolON0yHUBgdvLfNnctRMStGzPke0siLt
|
||||
RJvjqiL0Uw+blmLJU8lgMyLJ9ctXkiLJ/WflabN7VzmwYRWe5HzafGQJAg5uFjae
|
||||
VtAAHQgvbmdXB6brWvcMQmB8di7wjVedeigZvkt1z2V0FtBy8ybJaT5H6bX9Bf5C
|
||||
dS9r4mLhk/0ThthpRhRxsmupSL6e49nJaIk9q0UTEQVnorJXPcs4SPTIY51bCp6u
|
||||
cOebhNgndSxCiy0zSD7vRjNiyB/YNGZ9Uv/3DNTLleMZ9kZgfoKVpwYKrRL0IFT/
|
||||
cfS2OV1wxRxq668qaOfK
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAu0S3RxNzlqPWmcL9cQP3GMj7ov4HoMaU6gpUaYBnFUPo8SH5
|
||||
yUA0J3cqALxQ4qjomfoAI2RiXlBw6fQv9iGadOTC4fqJrfTfKQcpJt54/92cD1zg
|
||||
DtLsgzwDh4SEiEwMRLmQqg56u4mLo8sLcH0O26VtYQivT3zWWDErTJMOy7Bq+Qan
|
||||
CpD7jlk78RN/jaivB8cnWKJbKAKRBoYKJ8iJlYdT4NSo5LeaI78AF8znY38OaaGO
|
||||
TQK8LizkVB/l6HHrUaPAwukuNh5FPzKKnGMWvRLkbsLkIexrROm2kT4Kw7BGGmOA
|
||||
LMuN7CvNVedRf/ENWx2Sjf4KEHcUMM7/v5zi0wIDAQABAoIBAGyaWkvu/O7Uz2TW
|
||||
z1JWgVuvWzfYaKYV5FCicvfITn/npVUKZikPge+NTR+mFqaMXHDHqoLb+axGrGUR
|
||||
hysPq9q0vEx/lo763tyVWYlAJh4E8Dd8njganK0zBbz23kGJEOheUYY95XGTQBda
|
||||
bqTq8c3x7zAB8GGBvXDh+wFqm38GLyMF6T+YEzWJZqXfg31f1ldRvf6+VFwlLfz6
|
||||
cvTR7oUpYIsUeGE47kBs13SN7Oju6a355o/7wy9tOCRiu+r/ikXFh8rFGLfeTiwv
|
||||
R1dhYjcEYGxZUD8u64U+Cj4qR1P0gHJL0kbh22VMMqgALOc8FpndkjNdg1Nun2X8
|
||||
BWpsPwECgYEA7C9PfTOIZfxGBlCl05rmWex++/h5E5PbH1Cw/NGjIH1HjmAkO3+5
|
||||
WyMXhySOJ8yWyCBQ/nxqc0w7+TO4C7wQcEdZdUak25KJ74v0sfmWWrVw6kcnLU6k
|
||||
oawW/L2F2w7ET3zDoxKh4fOF34pfHpSbZk7XJ68YOfHpYVnP4efkQVMCgYEAyvrM
|
||||
KA7xjnsKumWh206ag3QEI0M/9uPHWmrh2164p7w1MtawccZTxYYJ5o5SsjTwbxkf
|
||||
0cAamp4qLInmRUxU1gk76tPYC3Ndp6Yf1C+dt0q/vtzyJetCDrdz8HHT1SpKbW0l
|
||||
g6z1I5FMwa6oWvWsfS++W51vsxUheNsOJ4uxKIECgYBwM7GRiw+7U3N4wItm0Wmp
|
||||
Qp642Tu7vzwTzmOmV3klkB6UVrwfv/ewgiVFQGqAIcNn42JW44g2qfq70oQWnws4
|
||||
K80l15+t6Bm7QUPH4Qg6o4O26IKGFZxEadqpyudyP7um/2B5cfqRuvzYS4YQowyI
|
||||
N+AirB3YOUJjyyTk7yMSnQKBgGNLpSvDg6+ryWe96Bwcq8G6s3t8noHsk81LlAl4
|
||||
oOSNUYj5NX+zAbATDizXWuUKuMPgioxVaa5RyVfYbelgme/KvKD32Sxg12P4BIIM
|
||||
eR79VifMdjjOiZYhcHojdPlGovo89qkfpxwrLF1jT8CPhj4HaRvwPIBiyekRYC9A
|
||||
Sv4BAoGAXCIC1xxAJP15osUuQjcM8KdsL1qw+LiPB2+cJJ2VMAZGV7CR2K0aCsis
|
||||
OwRaYM0jZKUpxzp1uwtfrfqbhdYsv+jIBkfwoShYZuo6MhbUrj0sffkhJC3WrT2z
|
||||
xafCFLFv1idzGvvNxatlp1DNKrndG2NS3syVAox9MnL5OMsvGM8=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,40 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
openssl genrsa -out CA.key 2048
|
||||
openssl req -x509 -new -nodes -key CA.key -days 1460 -subj '/CN=Swiftmailer CA/O=Swiftmailer/L=Paris/C=FR' -out CA.crt
|
||||
openssl x509 -in CA.crt -clrtrust -out CA.crt
|
||||
|
||||
openssl genrsa -out sign.key 2048
|
||||
openssl req -new -key sign.key -subj '/CN=Swiftmailer-User/O=Swiftmailer/L=Paris/C=FR' -out sign.csr
|
||||
openssl x509 -req -in sign.csr -CA CA.crt -CAkey CA.key -out sign.crt -days 1460 -addtrust emailProtection
|
||||
openssl x509 -in sign.crt -clrtrust -out sign.crt
|
||||
|
||||
rm sign.csr
|
||||
|
||||
openssl genrsa -out intermediate.key 2048
|
||||
openssl req -new -key intermediate.key -subj '/CN=Swiftmailer Intermediate/O=Swiftmailer/L=Paris/C=FR' -out intermediate.csr
|
||||
openssl x509 -req -in intermediate.csr -CA CA.crt -CAkey CA.key -set_serial 01 -out intermediate.crt -days 1460
|
||||
openssl x509 -in intermediate.crt -clrtrust -out intermediate.crt
|
||||
|
||||
rm intermediate.csr
|
||||
|
||||
openssl genrsa -out sign2.key 2048
|
||||
openssl req -new -key sign2.key -subj '/CN=Swiftmailer-User2/O=Swiftmailer/L=Paris/C=FR' -out sign2.csr
|
||||
openssl x509 -req -in sign2.csr -CA intermediate.crt -CAkey intermediate.key -set_serial 01 -out sign2.crt -days 1460 -addtrust emailProtection
|
||||
openssl x509 -in sign2.crt -clrtrust -out sign2.crt
|
||||
|
||||
rm sign2.csr
|
||||
|
||||
openssl genrsa -out encrypt.key 2048
|
||||
openssl req -new -key encrypt.key -subj '/CN=Swiftmailer-User/O=Swiftmailer/L=Paris/C=FR' -out encrypt.csr
|
||||
openssl x509 -req -in encrypt.csr -CA CA.crt -CAkey CA.key -CAcreateserial -out encrypt.crt -days 1460 -addtrust emailProtection
|
||||
openssl x509 -in encrypt.crt -clrtrust -out encrypt.crt
|
||||
|
||||
rm encrypt.csr
|
||||
|
||||
openssl genrsa -out encrypt2.key 2048
|
||||
openssl req -new -key encrypt2.key -subj '/CN=Swiftmailer-User2/O=Swiftmailer/L=Paris/C=FR' -out encrypt2.csr
|
||||
openssl x509 -req -in encrypt2.csr -CA CA.crt -CAkey CA.key -CAcreateserial -out encrypt2.crt -days 1460 -addtrust emailProtection
|
||||
openssl x509 -in encrypt2.crt -clrtrust -out encrypt2.crt
|
||||
|
||||
rm encrypt2.csr
|
||||
@@ -1,19 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDFjCCAf4CCQDULaNM+Q+g3TANBgkqhkiG9w0BAQUFADBMMRcwFQYDVQQDDA5T
|
||||
d2lmdG1haWxlciBDQTEUMBIGA1UECgwLU3dpZnRtYWlsZXIxDjAMBgNVBAcMBVBh
|
||||
cmlzMQswCQYDVQQGEwJGUjAeFw0xMzExMjcwODM5MTFaFw0xNzExMjYwODM5MTFa
|
||||
ME4xGTAXBgNVBAMMEFN3aWZ0bWFpbGVyLVVzZXIxFDASBgNVBAoMC1N3aWZ0bWFp
|
||||
bGVyMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3DQEB
|
||||
AQUAA4IBDwAwggEKAoIBAQCcNO+fVZBT2znmVwXXZ08n3G5WA1kyvqh9z4RBBZOD
|
||||
V46Gc1X9MMXr9+wzZBFkAckKaa6KsTkeUr4pC8XUBpQnakxH/kW9CaDPdOE+7wNo
|
||||
FkPfc6pjWWgpAVxdkrtk7pb4/aGQ++HUkqVu0cMpIcj/7ht7H+3QLZHybn+oMr2+
|
||||
FDnn8vPmHxVioinSrxKTlUITuLWS9ZZUTrDa0dG8UAv55A/Tba4T4McCPDpJSA4m
|
||||
9jrW321NGQUntQoItOJxagaueSvh6PveGV826gTXoU5X+YJ3I2OZUEQ2l6yByAzf
|
||||
nT+QlxPj5ikotFwL72HsenYtetynOO/k43FblAF/V/l7AgMBAAEwDQYJKoZIhvcN
|
||||
AQEFBQADggEBAJ048Sdb9Sw5OJM5L00OtGHgcT1B/phqdzSjkM/s64cg3Q20VN+F
|
||||
fZIIkOnxgyYWcpOWXcdNw2tm5OWhWPGsBcYgMac7uK/ukgoOJSjICg+TTS5kRo96
|
||||
iHtmImqkWc6WjNODh7uMnQ6DsZsscdl7Bkx5pKhgGnEdHr5GW8sztgXgyPQO5LUs
|
||||
YzCmR1RK1WoNMxwbPrGLgYdcpJw69ns5hJbZbMWwrdufiMjYWvTfBPABkk1JRCcY
|
||||
K6rRTAx4fApsw1kEIY8grGxyAzfRXLArpro7thJr0SIquZ8GpXkQT/mgRR8JD9Hp
|
||||
z9yhr98EnKzITE/yclGN4pUsuk9S3jiyzUU=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAnDTvn1WQU9s55lcF12dPJ9xuVgNZMr6ofc+EQQWTg1eOhnNV
|
||||
/TDF6/fsM2QRZAHJCmmuirE5HlK+KQvF1AaUJ2pMR/5FvQmgz3ThPu8DaBZD33Oq
|
||||
Y1loKQFcXZK7ZO6W+P2hkPvh1JKlbtHDKSHI/+4bex/t0C2R8m5/qDK9vhQ55/Lz
|
||||
5h8VYqIp0q8Sk5VCE7i1kvWWVE6w2tHRvFAL+eQP022uE+DHAjw6SUgOJvY61t9t
|
||||
TRkFJ7UKCLTicWoGrnkr4ej73hlfNuoE16FOV/mCdyNjmVBENpesgcgM350/kJcT
|
||||
4+YpKLRcC+9h7Hp2LXrcpzjv5ONxW5QBf1f5ewIDAQABAoIBADmuMm2botfUM+Ui
|
||||
bT3FIC2P8A5C3kUmsgEDB8sazAXL5w0uuanswKkJu2aepO1Q23PE4nbESlswIpf1
|
||||
iO9qHnsPfWt4MThEveTdO++JQrDEx/tTMq/M6/F4VysWa6wxjf4Taf2nhRSBsiTh
|
||||
wDcICri2q98jQyWELkhfFTR+yCHPsn6iNtzE2OpNv9ojKiSqck/sVjC39Z+uU/HD
|
||||
N4v0CPf9pDGkO+modaVGKf2TpvZT7Hpq/jsPzkk1h7BY7aWdZiIY4YkBkWYqZk8f
|
||||
0dsxKkOR2glfuEYNtcywG+4UGx3i1AY0mMu96hH5M1ACFmFrTCoodmWDnWy9wUpm
|
||||
leLmG8ECgYEAywWdryqcvLyhcmqHbnmUhCL9Vl4/5w5fr/5/FNvqArxSGwd2CxcN
|
||||
Jtkvu22cxWAUoe155eMc6GlPIdNRG8KdWg4sg0TN3Jb2jiHQ3QkHXUJlWU6onjP1
|
||||
g2n5h052JxVNGBEb7hr3U7ZMW6wnuYnGdYwCB9P3r5oGxxtfVRB8ygUCgYEAxPfy
|
||||
tAd3SNT8Sv/cciw76GYKbztUjJRXkLo6GOBGq/AQxP1NDWMuL2AES11YIahidMsF
|
||||
TMmM+zhkNHsd5P69p87FTMWx0cLoH0M9iQNK7Q6C1luTjLf5DTFuk+nHGErM4Drs
|
||||
+6Ly1Z4KLXfXgBDD8Ce6U9+W3RrCc36poGZvjX8CgYEAna0P6WJr9r19mhIYevmc
|
||||
Gf/ex7xNXxMvx80dP8MIfPVrwyhJSpWtljVpt+SKtFRJ0fVRDfUUl4Bqf/fR74B3
|
||||
muCVO6ItTBxHAt5Ki9CeUpTlh7XqiWwLSvP8Y1TRuMr3ZDCtg4CYBAD6Ttxmwde6
|
||||
NcL2NMQwgsZaazrcEIHMmU0CgYEAl/Mn2tZ/oUIdt8YWzEVvmeNOXW0J1sGBo/bm
|
||||
ZtZt7qpuZWl7jb5bnNSXu4QxPxXljnAokIpUJmHke9AWydfze4c6EfXZLhcMd0Gq
|
||||
MQ7HOIWfTbqr4zzx9smRoq4Ql57s2nba521XpJAdDeKL7xH/9j7PsXCls8C3Dd5D
|
||||
AajEmgUCgYAGEdn6tYxIdX7jF39E3x7zHQf8jHIoQ7+cLTLtd944mSGgeqMfbiww
|
||||
CoUa+AAUqjdAD5ViAyJrA+gmDtWpkFnJZtToXYwfUF2o3zRo4k1DeBrVbFqwSQkE
|
||||
omrfiBGtviYIPdqQLE34LYpWEooNPraqO9qTyc+9w5038u2OFS+WmQ==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,19 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDFzCCAf8CCQDULaNM+Q+g3jANBgkqhkiG9w0BAQUFADBMMRcwFQYDVQQDDA5T
|
||||
d2lmdG1haWxlciBDQTEUMBIGA1UECgwLU3dpZnRtYWlsZXIxDjAMBgNVBAcMBVBh
|
||||
cmlzMQswCQYDVQQGEwJGUjAeFw0xMzExMjcwODM5MTJaFw0xNzExMjYwODM5MTJa
|
||||
ME8xGjAYBgNVBAMMEVN3aWZ0bWFpbGVyLVVzZXIyMRQwEgYDVQQKDAtTd2lmdG1h
|
||||
aWxlcjEOMAwGA1UEBwwFUGFyaXMxCzAJBgNVBAYTAkZSMIIBIjANBgkqhkiG9w0B
|
||||
AQEFAAOCAQ8AMIIBCgKCAQEAw4AoYVYss2sa1BWJAJpK6gVemjXrp1mVXVpb1/z6
|
||||
SH15AGsp3kiNXsMpgvsdofbqC/5HXrw2G8gWqo+uh6GuK67+Tvp7tO2aD4+8CZzU
|
||||
K1cffj7Pbx95DUPwXckv79PT5ZcuyeFaVo92aug11+gS/P8n0WXSlzZxNuZ1f3G2
|
||||
r/IgwfNKZlarEf1Ih781L2SwmyveW/dtsV2pdrd4IZwsV5SOF2zBFIXSuhPN0c+m
|
||||
mtwSJe+Ow1udLX4KJkAX8sGVFJ5P5q4s2nS9vLkkj7X6YRQscbyJO9L7e1TksRqL
|
||||
DLxZwiko6gUhp4/bIs1wDj5tzkQBi4qXviRq3i7A9b2d0QIDAQABMA0GCSqGSIb3
|
||||
DQEBBQUAA4IBAQAj8iARhPB2DA3YfT5mJJrgU156Sm0Z3mekAECsr+VqFZtU/9Dz
|
||||
pPFYEf0hg61cjvwhLtOmaTB+50hu1KNNlu8QlxAfPJqNxtH85W0CYiZHJwW9eSTr
|
||||
z1swaHpRHLDUgo3oAXdh5syMbdl0MWos0Z14WP5yYu4IwJXs+j2JRW70BICyrNjm
|
||||
d+AjCzoYjKMdJkSj4uxQEOuW2/5veAoDyU+kHDdfT7SmbyoKu+Pw4Xg/XDuKoWYg
|
||||
w5/sRiw5vxsmOr9+anspDHdP9rUe1JEfwAJqZB3fwdqEyxu54Xw/GedG4wZBEJf0
|
||||
ZcS1eh31emcjYUHQa1IA93jcFSmXzJ+ftJrY
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAw4AoYVYss2sa1BWJAJpK6gVemjXrp1mVXVpb1/z6SH15AGsp
|
||||
3kiNXsMpgvsdofbqC/5HXrw2G8gWqo+uh6GuK67+Tvp7tO2aD4+8CZzUK1cffj7P
|
||||
bx95DUPwXckv79PT5ZcuyeFaVo92aug11+gS/P8n0WXSlzZxNuZ1f3G2r/IgwfNK
|
||||
ZlarEf1Ih781L2SwmyveW/dtsV2pdrd4IZwsV5SOF2zBFIXSuhPN0c+mmtwSJe+O
|
||||
w1udLX4KJkAX8sGVFJ5P5q4s2nS9vLkkj7X6YRQscbyJO9L7e1TksRqLDLxZwiko
|
||||
6gUhp4/bIs1wDj5tzkQBi4qXviRq3i7A9b2d0QIDAQABAoIBAH8RvK1PmqxfkEeL
|
||||
W8oVf13OcafgJjRW6NuNkKa5mmAlldFs1gDRvXl7dm7ZE3CjkYqMEw2DXdP+4KSp
|
||||
0TH9J7zi+A6ThnaZ/QniTcEdu1YUQbcH0kIS/dZec0wyKUNDtrXC5zl2jQY4Jyrj
|
||||
laOpBzaEDfhvq0p3q2yYrIRSgACpSEVEsfPoHrxtlLhfMkVNe8P0nkQkzdwou5MQ
|
||||
MZKV4JUopLHLgPH6IXQCqA1wzlU32yZ86w88GFcBVLkwlLJCKbuAo7yxMCD+nzvA
|
||||
xm5NuF1kzpP0gk+kZRXF+rFEV4av/2kSS+n8IeUBQZrxovLBuQHVDvJXoqcEjmlh
|
||||
ZUltznUCgYEA4inwieePfb7kh7L/ma5OLLn+uCNwzVw9LayzXT1dyPravOnkHl6h
|
||||
MgaoTspqDyU8k8pStedRrr5dVYbseni/A4WSMGvi4innqSXBQGp64TyeJy/e+LrS
|
||||
ypSWQ6RSJkCxI5t8s4mOpR7FMcdE34I5qeA4G5RS1HIacn7Hxc7uXtcCgYEA3Uqn
|
||||
E7EDfNfYdZm6AikvE6x64oihWI0x47rlkLu6lf6ihiF1dbfaEN+IAaIxQ/unGYwU
|
||||
130F0TUwarXnVkeBIRlij4fXhExyd7USSQH1VpqmIqDwsS2ojrzQVMo5UcH+A22G
|
||||
bbHPtwJNmw8a7yzTPWo2/vnjgV2OaXEQ9vCVG5cCgYEAu1kEoihJDGBijSqxY4wp
|
||||
xBE7OSxamDNtlnV2i6l3FDMBmfaieqnnHDq5l7NDklJFUSQLyhXZ60hUprHDGV0G
|
||||
1pMCW8wzQSh3d/4HjSXnrsd5N3sHWMHiNeBKbbQkPP3f/2AhN9SebpgDwE2S9xe4
|
||||
TsmnkOkYiFYRJIFzWaAmhDcCgYEAwxRCgZt0xaPKULG6RpljxOYyVm24PsYKCwYB
|
||||
xjuYWw5k2/W3BJWVCXblAPuojpPUVTMmVGkErc9D5W6Ch471iOZF+t334cs6xci8
|
||||
W9v8GeKvPqu+Q5NKmrpctcKoESkA8qik7yLnSCAhpeYFCn/roKJ35QMJyktddhqU
|
||||
p/yilfUCgYBxZ6YmFjYH6l5SxQdcfa5JQ2To8lZCfRJwB65EyWj4pKH4TaWFS7vb
|
||||
50WOGTBwJgyhTKLCO3lOmXIUyIwC+OO9xzaeRCBjqEhpup/Ih3MsfMEd6BZRVK5E
|
||||
IxtmIWba5HQ52k8FKHeRrRB7PSVSADUN2pUFkLudH+j/01kSZyJoLA==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,19 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDFjCCAf4CAQEwDQYJKoZIhvcNAQEFBQAwTDEXMBUGA1UEAwwOU3dpZnRtYWls
|
||||
ZXIgQ0ExFDASBgNVBAoMC1N3aWZ0bWFpbGVyMQ4wDAYDVQQHDAVQYXJpczELMAkG
|
||||
A1UEBhMCRlIwHhcNMTQxMTIwMTMyNTQxWhcNMTgxMTE5MTMyNTQxWjBWMSEwHwYD
|
||||
VQQDDBhTd2lmdG1haWxlciBJbnRlcm1lZGlhdGUxFDASBgNVBAoMC1N3aWZ0bWFp
|
||||
bGVyMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3DQEB
|
||||
AQUAA4IBDwAwggEKAoIBAQDSgEhftX6f1wV+uqWl4J+zwCn8fHaLZT6GZ0Gs9ThE
|
||||
4e+4mkLG1rvSEIJon8U0ic8Zph1UGa1Grveh5bgbldHlFxYSsCCyDGgixRvRWNhI
|
||||
KuO+SxaIZChqqKwVn3aNQ4BZOSo/MjJ/jQyr9BMgMmdxlHR3e1wkkeAkW//sOsfu
|
||||
xQGF1h9yeQvuu/GbG6K7vHSGOGd5O3G7bftfQ7l78TMqeJ7jV32AdJeuO5MD4dRn
|
||||
W4CQLTaeribLN0MKn35UdSiFoZxKHqqWcgtl5xcJWPOmq6CsAJ2Eo90kW/BHOrLv
|
||||
10h6Oan9R1PdXSvSCvVnXY3Kz30zofw305oA/KJk/hVzAgMBAAEwDQYJKoZIhvcN
|
||||
AQEFBQADggEBABijZ2NNd05Js5VFNr4uyaydam9Yqu/nnrxbPRbAXPlCduydu2Gd
|
||||
d1ekn3nblMJ87Bc7zVyHdAQD8/AfS1LOKuoWHpTzmlpIL+8T5sbCYG5J1jKdeLkh
|
||||
7L/UD5v1ACgA33oKtN8GzcrIq8Zp73r0n+c3hFCfDYRSZRCxGyIf3qgU2LBOD0A3
|
||||
wTff/N8E/p3WaJX9VnuQ7xyRMOubDuqJnlo5YsFv7wjyGOIAz9afZzcEbH6czt/t
|
||||
g0Xc/kGr/fkAjUu+z3ZfE4247Gut5m3hEVwWkpEEzQo4osX/BEX20Q2nPz9WBq4a
|
||||
pK3qNNGwAqS4gdE3ihOExMWxAKgr9d2CcU4=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEA0oBIX7V+n9cFfrqlpeCfs8Ap/Hx2i2U+hmdBrPU4ROHvuJpC
|
||||
xta70hCCaJ/FNInPGaYdVBmtRq73oeW4G5XR5RcWErAgsgxoIsUb0VjYSCrjvksW
|
||||
iGQoaqisFZ92jUOAWTkqPzIyf40Mq/QTIDJncZR0d3tcJJHgJFv/7DrH7sUBhdYf
|
||||
cnkL7rvxmxuiu7x0hjhneTtxu237X0O5e/EzKnie41d9gHSXrjuTA+HUZ1uAkC02
|
||||
nq4myzdDCp9+VHUohaGcSh6qlnILZecXCVjzpqugrACdhKPdJFvwRzqy79dIejmp
|
||||
/UdT3V0r0gr1Z12Nys99M6H8N9OaAPyiZP4VcwIDAQABAoIBAQDLJiKyu2XIvKsA
|
||||
8wCKZY262+mpUjTVso/1BhHL6Zy0XZgMgFORsgrxYB16+zZGzfiguD/1uhIP9Svn
|
||||
gtt7Q8udW/phbrkfG/okFDYUg7m3bCz+qVjFqGOZC8+Hzq2LB2oGsbSj6L3zexyP
|
||||
lq4elIZghvUfml4CrQW0EVWbld79/kF7XHABcIOk2+3f63XAQWkjdFNxj5+z6TR0
|
||||
52Rv7SmRioAsukW9wr77G3Luv/0cEzDFXgGW5s0wO+rJg28smlsIaj+Y0KsptTig
|
||||
reQvReAT/S5ZxEp4H6WtXQ1WmaliMB0Gcu4TKB0yE8DoTeCePuslo9DqGokXYT66
|
||||
oqtcVMqBAoGBAPoOL9byNNU/bBNDWSCiq8PqhSjl0M4vYBGqtgMXM4GFOJU+W2nX
|
||||
YRJbbxoSd/DKjnxEsR6V0vDTDHj4ZSkgmpEmVhEdAiwUwaZ0T8YUaCPhdiAENo5+
|
||||
zRBWVJcvAC2XKTK1hy5D7Z5vlC32HHygYqitU+JsK4ylvhrdeOcGx5cfAoGBANeB
|
||||
X0JbeuqBEwwEHZqYSpzmtB+IEiuYc9ARTttHEvIWgCThK4ldAzbXhDUIQy3Hm0sL
|
||||
PzDA33furNl2WwB+vmOuioYMNjArKrfg689Aim1byg4AHM5XVQcqoDSOABtI55iP
|
||||
E0hYDe/d4ema2gk1uR/mT4pnLnk2VzRKsHUbP9stAoGBAKjyIuJwPMADnMqbC0Hg
|
||||
hnrVHejW9TAJlDf7hgQqjdMppmQ3gF3PdjeH7VXJOp5GzOQrKRxIEABEJ74n3Xlf
|
||||
HO+K3kWrusb7syb6mNd0/DOZ5kyVbCL0iypJmdeXmuAyrFQlj9LzdD1Cl/RBv1d4
|
||||
qY/bo7xsZzQc24edMU2uJ/XzAoGBAMHChA95iK5HlwR6vtM8kfk4REMFaLDhxV8R
|
||||
8MCeyp33NQfzm91JT5aDd07nOt9yVGHInuwKveFrKuXq0C9FxZCCYfHcEOyGI0Zo
|
||||
aBxTfyKMIMMtvriXNM/Yt2oJMndVuUUlfsTQxtcfu/r5S4h0URopTOK3msVI4mcV
|
||||
sEnaUjORAoGAGDnslKYtROQMXTe4sh6CoJ32J8UZVV9M+8NLus9rO0v/eZ/pIFxo
|
||||
MXGrrrl51ScqahCQ+DXHzpLvInsdlAJvDP3ymhb7H2xGsyvb3x2YgsLmr1YVOnli
|
||||
ISbCssno3vZyFU1TDjeEIKqZHc92byHNMjMuhmlaA25g8kb0cCO76EA=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,19 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDFjCCAf4CCQDULaNM+Q+g3DANBgkqhkiG9w0BAQUFADBMMRcwFQYDVQQDDA5T
|
||||
d2lmdG1haWxlciBDQTEUMBIGA1UECgwLU3dpZnRtYWlsZXIxDjAMBgNVBAcMBVBh
|
||||
cmlzMQswCQYDVQQGEwJGUjAeFw0xMzExMjcwODM5MTBaFw0xNzExMjYwODM5MTBa
|
||||
ME4xGTAXBgNVBAMMEFN3aWZ0bWFpbGVyLVVzZXIxFDASBgNVBAoMC1N3aWZ0bWFp
|
||||
bGVyMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3DQEB
|
||||
AQUAA4IBDwAwggEKAoIBAQCTe8ZouyjVGgqlljhaswYqLj7icMoHq+Qg13CE+zJg
|
||||
tl2/UzyPhAd3WWOIvlQ0lu+E/n0bXrS6+q28DrQ3UgJ9BskzzLz15qUO12b92AvG
|
||||
vLJ+9kKuiM5KXDljOAsXc7/A9UUGwEFA1D0mkeMmkHuiQavAMkzBLha22hGpg/hz
|
||||
VbE6W9MGna0szd8yh38IY1M5uR+OZ0dG3KbVZb7H3N0OLOP8j8n+4YtAGAW+Onz/
|
||||
2CGPfZ1kaDMvY/WTZwyGeA4FwCPy1D8tfeswqKnWDB9Sfl8hns5VxnoJ3dqKQHeX
|
||||
iC4OMfQ0U4CcuM5sVYJZRNNwP7/TeUh3HegnOnuZ1hy9AgMBAAEwDQYJKoZIhvcN
|
||||
AQEFBQADggEBAAEPjGt98GIK6ecAEat52aG+8UP7TuZaxoH3cbZdhFTafrP8187F
|
||||
Rk5G3LCPTeA/QIzbHppA4fPAiS07OVSwVCknpTJbtKKn0gmtTZxThacFHF2NlzTH
|
||||
XxM5bIbkK3jzIF+WattyTSj34UHHfaNAmvmS7Jyq6MhjSDbcQ+/dZ9eo2tF/AmrC
|
||||
+MBhyH8aUYwKhTOQQh8yC11niziHhGO99FQ4tpuD9AKlun5snHq4uK9AOFe8VhoR
|
||||
q2CqX5g5v8OAtdlvzhp50IqD4BNOP+JrUxjGLHDG76BZZIK2Ai1eBz+GhRlIQru/
|
||||
8EhQzd94mdFEPblGbmuD2QXWLFFKLiYOwOc=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAk3vGaLso1RoKpZY4WrMGKi4+4nDKB6vkINdwhPsyYLZdv1M8
|
||||
j4QHd1ljiL5UNJbvhP59G160uvqtvA60N1ICfQbJM8y89ealDtdm/dgLxryyfvZC
|
||||
rojOSlw5YzgLF3O/wPVFBsBBQNQ9JpHjJpB7okGrwDJMwS4WttoRqYP4c1WxOlvT
|
||||
Bp2tLM3fMod/CGNTObkfjmdHRtym1WW+x9zdDizj/I/J/uGLQBgFvjp8/9ghj32d
|
||||
ZGgzL2P1k2cMhngOBcAj8tQ/LX3rMKip1gwfUn5fIZ7OVcZ6Cd3aikB3l4guDjH0
|
||||
NFOAnLjObFWCWUTTcD+/03lIdx3oJzp7mdYcvQIDAQABAoIBAH2vrw/T6GFrlwU0
|
||||
twP8q1VJIghCDLpq77hZQafilzU6VTxWyDaaUu6QPDXt1b8Xnjnd02p+1FDAj0zD
|
||||
zyuR9VLtdIxzf9mj3KiAQ2IzOx3787YlUgCB0CQo4jM/MJyk5RahL1kogLOp7A8x
|
||||
pr5XxTUq+B6L/0Nmbq8XupOXRyWp53amZ5N8sgWDv4oKh9fqgAhxbSG6KUkTmhYs
|
||||
DLinWg86Q28pSn+eivf4dehR56YwtTBVguXW3WKO70+GW1RotSrS6e6SSxfKYksZ
|
||||
a7/J1hCmJkEE3+4C8BpcI0MelgaK66ocN0pOqDF9ByxphARqyD7tYCfoS2P8gi81
|
||||
XoiZJaECgYEAwqx4AnDX63AANsfKuKVsEQfMSAG47SnKOVwHB7prTAgchTRcDph1
|
||||
EVOPtJ+4ssanosXzLcN/dCRlvqLEqnKYAOizy3C56CyRguCpO1AGbRpJjRmHTRgA
|
||||
w8iArhM07HgJ3XLFn99V/0bsPCMxW8dje1ZMjKjoQtDrXRQMtWaVY+UCgYEAwfGi
|
||||
f0If6z7wJj9gQUkGimWDAg/bxDkvEeh3nSD/PQyNiW0XDclcb3roNPQsal2ZoMwt
|
||||
f1bwkclw7yUCIZBvXWEkZapjKCdseTp6nglScxr8GAzfN9p5KQl+OS3GzC6xZf6C
|
||||
BsZQ5ucsHTHsCAi3WbwGK829z9c7x0qRwgwu9/kCgYEAsqwEwYi8Q/RZ3e1lXC9H
|
||||
jiHwFi6ugc2XMyoJscghbnkLZB54V1UKLUraXFcz97FobnbsCJajxf8Z+uv9QMtI
|
||||
Q51QV2ow1q0BKHP2HuAF5eD4nK5Phix/lzHRGPO74UUTGNKcG22pylBXxaIvTSMl
|
||||
ZTABth/YfGqvepBKUbvDZRkCgYB5ykbUCW9H6D8glZ3ZgYU09ag+bD0CzTIs2cH7
|
||||
j1QZPz/GdBYNF00PyKv3TPpzVRH7cxyDIdJyioB7/M6Iy03T4wPbQBOCjLdGrZ2A
|
||||
jrQTCngSlkq6pVx+k7KLL57ua8gFF70JihIV3kfKkaX6KZcSJ8vsSAgRc8TbUo2T
|
||||
wNjh6QKBgDyxw4bG2ULs+LVaHcnp7nizLgRGXJsCkDICjla6y0eCgAnG8fSt8CcG
|
||||
s5DIfJeVs/NXe/NVNuVrfwsUx0gBOirtFwQStvi5wJnY/maGAyjmgafisNFgAroT
|
||||
aM5f+wyGPQeGCs7bj7JWY7Nx9lkyuUV7DdKBTZNMOe51K3+PTEL3
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,19 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDGTCCAgECAQEwDQYJKoZIhvcNAQEFBQAwVjEhMB8GA1UEAwwYU3dpZnRtYWls
|
||||
ZXIgSW50ZXJtZWRpYXRlMRQwEgYDVQQKDAtTd2lmdG1haWxlcjEOMAwGA1UEBwwF
|
||||
UGFyaXMxCzAJBgNVBAYTAkZSMB4XDTE0MTEyMDEzMjYyNloXDTE4MTExOTEzMjYy
|
||||
NlowTzEaMBgGA1UEAwwRU3dpZnRtYWlsZXItVXNlcjIxFDASBgNVBAoMC1N3aWZ0
|
||||
bWFpbGVyMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQDbr1m4z/rzFS/DxUUQIhKNx19oAeGYLt3niaEP
|
||||
twfvBMNB80gMgM9d+XtqrPAMPeY/2C8t5NlChNPKMcR70JBKdmlSH4/aTjaIfWmD
|
||||
PoZJjvRRXINZgSHNKIt4ZGAN/EPFr19CBisV4iPxzu+lyIbbkaZJ/qtyatlP7m/q
|
||||
8TnykFRlyxNEveCakpcXeRd3YTFGKWoED+/URhVc0cCPZVjoeSTtPHAYBnC29lG5
|
||||
VFbq6NBQiyF4tpjOHRarq6G8PtQFH9CpAZg5bPk3bqka9C8mEr5jWfrM4EHtUkTl
|
||||
CwVLOQRBsz/nMBT27pXZh18GU0hc3geNDN4kqaeqgNBo0mblAgMBAAEwDQYJKoZI
|
||||
hvcNAQEFBQADggEBAAHDMuv6oxWPsTQWWGWWFIk7QZu3iogMqFuxhhQxg8BE37CT
|
||||
Vt1mBVEjYGMkWhMSwWBMWuP6yuOZecWtpp6eOie/UKGg1XoW7Y7zq2aQaP7YPug0
|
||||
8Lgq1jIo7iO2b6gZeMtLiTZrxyte0z1XzS3wy7ZC9mZjYd7QE7mZ+/rzQ0x5zjOp
|
||||
G8b3msS/yYYJCMN+HtHln++HOGmm6uhvbsHTfvvZvtl7F5vJ5WhGGlUfjhanSEtZ
|
||||
1RKx+cbgIv1eFOGO1OTuZfEuKdLb0T38d/rjLeI99nVVKEIGtLmX4dj327GHe/D3
|
||||
aPr2blF2gOvlzkfN9Vz6ZUE2s3rVBeCg2AVseYQ=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA269ZuM/68xUvw8VFECISjcdfaAHhmC7d54mhD7cH7wTDQfNI
|
||||
DIDPXfl7aqzwDD3mP9gvLeTZQoTTyjHEe9CQSnZpUh+P2k42iH1pgz6GSY70UVyD
|
||||
WYEhzSiLeGRgDfxDxa9fQgYrFeIj8c7vpciG25GmSf6rcmrZT+5v6vE58pBUZcsT
|
||||
RL3gmpKXF3kXd2ExRilqBA/v1EYVXNHAj2VY6Hkk7TxwGAZwtvZRuVRW6ujQUIsh
|
||||
eLaYzh0Wq6uhvD7UBR/QqQGYOWz5N26pGvQvJhK+Y1n6zOBB7VJE5QsFSzkEQbM/
|
||||
5zAU9u6V2YdfBlNIXN4HjQzeJKmnqoDQaNJm5QIDAQABAoIBAAM2FvuqnqJ7Bs23
|
||||
zoCj3t2PsodUr7WHydqemmoeZNFLoocORVlZcK6Q/QrcKE4lgX4hbN8g30QnqOjl
|
||||
vVeJ/vH3tSZsK7AnQIjSPH6cpV3h5xRhY9IlHxdepltGLFlH/L2hCKVwbaTOP3RD
|
||||
cCFeQwpmoKWoQV1UzoRqmdw3Vn+DMaUULomLVR9aSW9PnKeFL+tPWShf7GmVISfM
|
||||
2H6xKw/qT0XAX59ZHA1laxSFVvbV5ZcKrBOFMV407Vzw2d3ojmfEzNsHjUVBXX8j
|
||||
B5nK1VeJiTVmcoVhnRX7tXESDaZy+Kv38pqOmc8Svn70lDJ35SM2EpWnX39w5LsQ
|
||||
29NsIUECgYEA/vNKiMfVmmZNQrpcuHQe5adlmz9+I4xJ4wbRzrS7czpbKF0/iaPf
|
||||
dKoVz67yYHOJCBHTVaXWkElQsq1mkyuFt/cc0ReJXO8709+t+6ULsE50cLQm/HN5
|
||||
npg3gw0Ls/9dy/cHM5SdVIHMBm9oQ65rXup/dqWC8Dz2cAAOQhIPwx0CgYEA3Jbk
|
||||
DPdUlrj4sXcE3V/CtmBuK9Xq1xolJt026fYCrle0YhdMKmchRBDCc6BzM+F/vDyC
|
||||
llPfQu8TDXK40Oan7GbxMdoLqKK9gSIq1dvfG1YMMz8OrBcX8xKe61KFRWd7QSBJ
|
||||
BcY575NzYHapOHVGnUJ68j8zCow0gfb7q6iK4GkCgYEAz2mUuKSCxYL21hORfUqT
|
||||
HFjMU7oa38axEa6pn9XvLjZKlRMPruWP1HTPG9ADRa6Yy+TcnrA1V9sdeM+TRKXC
|
||||
usCiRAU27lF+xccS30gNs1iQaGRX10gGqJzDhK1nWP+nClmlFTSRrn+OQan/FBjh
|
||||
Jy31lsveM54VC1cwQlY5Vo0CgYEArtjfnLNzFiE55xjq/znHUd4vlYlzItrzddHE
|
||||
lEBOsbiNH29ODRI/2P7b0uDsT8Q/BoqEC/ohLqHn3TIA8nzRv91880HdGecdBL17
|
||||
bJZiSv2yn/AshhWsAxzQYMDBKFk05lNb7jrIc3DR9DU6PqketsoaP+f+Yi7t89I8
|
||||
fD0VD3kCgYAaJCoQshng/ijiHF/RJXLrXXHJSUmaOfbweX/mzFup0YR1LxUjcv85
|
||||
cxvwc41Y2iI5MwUXyX97/GYKeoobzWZy3XflNWtg04rcInVaPsb/OOFDDqI+MkzT
|
||||
B4PcCurOmjzcxHMVE34CYvl3YVwWrPb5JO1rYG9T2gKUJnLU6qG4Bw==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Swift Mailer V4 accpetance test configuration.
|
||||
|
||||
YOU ONLY NEED TO EDIT THIS FILE IF YOU WISH TO RUN THE ACCEPTANCE TESTS.
|
||||
|
||||
The acceptance tests are run by default when "All Tests" are run with the
|
||||
testing suite, however, without configuration options here only the unit tests
|
||||
will be run and the acceptance tests will be skipped.
|
||||
|
||||
You can fill out only the parts you know and leave the other bits.
|
||||
*/
|
||||
|
||||
/*
|
||||
Defines: The name and port of a SMTP server you can connect to.
|
||||
Recommended: smtp.gmail.com:25
|
||||
*/
|
||||
define('SWIFT_SMTP_HOST', 'localhost:4456');
|
||||
|
||||
/*
|
||||
Defines: An SMTP server and port which uses TLS encryption.
|
||||
Recommended: smtp.gmail.com:465
|
||||
*/
|
||||
define('SWIFT_TLS_HOST', 'smtp.gmail.com:465');
|
||||
|
||||
/*
|
||||
Defines: An SMTP server and port which uses SSL encryption.
|
||||
Recommended: smtp.gmail.com:465
|
||||
*/
|
||||
define('SWIFT_SSL_HOST', 'smtp.gmail.com:465');
|
||||
|
||||
/*
|
||||
Defines: The path to a sendmail binary (one which can run in -bs mode).
|
||||
Recommended: /usr/sbin/sendmail
|
||||
*/
|
||||
define('SWIFT_SENDMAIL_PATH', '/usr/sbin/sendmail -bs');
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'swift_required.php';
|
||||
require_once __DIR__.'/Mime/AttachmentAcceptanceTest.php';
|
||||
|
||||
class Swift_AttachmentAcceptanceTest extends Swift_Mime_AttachmentAcceptanceTest
|
||||
{
|
||||
protected function _createAttachment()
|
||||
{
|
||||
return Swift_Attachment::newInstance();
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_ByteStream_FileByteStreamAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_testFile;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_testFile = sys_get_temp_dir().'/swift-test-file'.__CLASS__;
|
||||
file_put_contents($this->_testFile, 'abcdefghijklm');
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
unlink($this->_testFile);
|
||||
}
|
||||
|
||||
public function testFileDataCanBeRead()
|
||||
{
|
||||
$file = $this->_createFileStream($this->_testFile);
|
||||
$str = '';
|
||||
while (false !== $bytes = $file->read(8192)) {
|
||||
$str .= $bytes;
|
||||
}
|
||||
$this->assertEquals('abcdefghijklm', $str);
|
||||
}
|
||||
|
||||
public function testFileDataCanBeReadSequentially()
|
||||
{
|
||||
$file = $this->_createFileStream($this->_testFile);
|
||||
$this->assertEquals('abcde', $file->read(5));
|
||||
$this->assertEquals('fghijklm', $file->read(8));
|
||||
$this->assertFalse($file->read(1));
|
||||
}
|
||||
|
||||
public function testFilenameIsReturned()
|
||||
{
|
||||
$file = $this->_createFileStream($this->_testFile);
|
||||
$this->assertEquals($this->_testFile, $file->getPath());
|
||||
}
|
||||
|
||||
public function testFileCanBeWrittenTo()
|
||||
{
|
||||
$file = $this->_createFileStream($this->_testFile, true);
|
||||
$file->write('foobar');
|
||||
$this->assertEquals('foobar', $file->read(8192));
|
||||
}
|
||||
|
||||
public function testReadingFromThenWritingToFile()
|
||||
{
|
||||
$file = $this->_createFileStream($this->_testFile, true);
|
||||
$file->write('foobar');
|
||||
$this->assertEquals('foobar', $file->read(8192));
|
||||
$file->write('zipbutton');
|
||||
$this->assertEquals('zipbutton', $file->read(8192));
|
||||
}
|
||||
|
||||
public function testWritingToFileWithCanonicalization()
|
||||
{
|
||||
$file = $this->_createFileStream($this->_testFile, true);
|
||||
$file->addFilter($this->_createFilter(array("\r\n", "\r"), "\n"), 'allToLF');
|
||||
$file->write("foo\r\nbar\r");
|
||||
$file->write("\nzip\r\ntest\r");
|
||||
$file->flushBuffers();
|
||||
$this->assertEquals("foo\nbar\nzip\ntest\n", file_get_contents($this->_testFile));
|
||||
}
|
||||
|
||||
public function testWritingWithFulleMessageLengthOfAMultipleOf8192()
|
||||
{
|
||||
$file = $this->_createFileStream($this->_testFile, true);
|
||||
$file->addFilter($this->_createFilter(array("\r\n", "\r"), "\n"), 'allToLF');
|
||||
$file->write('');
|
||||
$file->flushBuffers();
|
||||
$this->assertEquals('', file_get_contents($this->_testFile));
|
||||
}
|
||||
|
||||
public function testBindingOtherStreamsMirrorsWriteOperations()
|
||||
{
|
||||
$file = $this->_createFileStream($this->_testFile, true);
|
||||
$is1 = $this->_createMockInputStream();
|
||||
$is2 = $this->_createMockInputStream();
|
||||
|
||||
$is1->expects($this->at(0))
|
||||
->method('write')
|
||||
->with('x');
|
||||
$is1->expects($this->at(1))
|
||||
->method('write')
|
||||
->with('y');
|
||||
$is2->expects($this->at(0))
|
||||
->method('write')
|
||||
->with('x');
|
||||
$is2->expects($this->at(1))
|
||||
->method('write')
|
||||
->with('y');
|
||||
|
||||
$file->bind($is1);
|
||||
$file->bind($is2);
|
||||
|
||||
$file->write('x');
|
||||
$file->write('y');
|
||||
}
|
||||
|
||||
public function testBindingOtherStreamsMirrorsFlushOperations()
|
||||
{
|
||||
$file = $this->_createFileStream(
|
||||
$this->_testFile, true
|
||||
);
|
||||
$is1 = $this->_createMockInputStream();
|
||||
$is2 = $this->_createMockInputStream();
|
||||
|
||||
$is1->expects($this->once())
|
||||
->method('flushBuffers');
|
||||
$is2->expects($this->once())
|
||||
->method('flushBuffers');
|
||||
|
||||
$file->bind($is1);
|
||||
$file->bind($is2);
|
||||
|
||||
$file->flushBuffers();
|
||||
}
|
||||
|
||||
public function testUnbindingStreamPreventsFurtherWrites()
|
||||
{
|
||||
$file = $this->_createFileStream($this->_testFile, true);
|
||||
$is1 = $this->_createMockInputStream();
|
||||
$is2 = $this->_createMockInputStream();
|
||||
|
||||
$is1->expects($this->at(0))
|
||||
->method('write')
|
||||
->with('x');
|
||||
$is1->expects($this->at(1))
|
||||
->method('write')
|
||||
->with('y');
|
||||
$is2->expects($this->once())
|
||||
->method('write')
|
||||
->with('x');
|
||||
|
||||
$file->bind($is1);
|
||||
$file->bind($is2);
|
||||
|
||||
$file->write('x');
|
||||
|
||||
$file->unbind($is2);
|
||||
|
||||
$file->write('y');
|
||||
}
|
||||
|
||||
private function _createFilter($search, $replace)
|
||||
{
|
||||
return new Swift_StreamFilters_StringReplacementFilter($search, $replace);
|
||||
}
|
||||
|
||||
private function _createMockInputStream()
|
||||
{
|
||||
return $this->getMockBuilder('Swift_InputByteStream')->getMock();
|
||||
}
|
||||
|
||||
private function _createFileStream($file, $writable = false)
|
||||
{
|
||||
return new Swift_ByteStream_FileByteStream($file, $writable);
|
||||
}
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_CharacterReaderFactory_SimpleCharacterReaderFactoryAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_factory;
|
||||
private $_prefix = 'Swift_CharacterReader_';
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
|
||||
}
|
||||
|
||||
public function testCreatingUtf8Reader()
|
||||
{
|
||||
foreach (array('utf8', 'utf-8', 'UTF-8', 'UTF8') as $utf8) {
|
||||
$reader = $this->_factory->getReaderFor($utf8);
|
||||
$this->assertInstanceOf($this->_prefix.'Utf8Reader', $reader);
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingIso8859XReaders()
|
||||
{
|
||||
$charsets = array();
|
||||
foreach (range(1, 16) as $number) {
|
||||
foreach (array('iso', 'iec') as $body) {
|
||||
$charsets[] = $body.'-8859-'.$number;
|
||||
$charsets[] = $body.'8859-'.$number;
|
||||
$charsets[] = strtoupper($body).'-8859-'.$number;
|
||||
$charsets[] = strtoupper($body).'8859-'.$number;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($charsets as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(1, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingWindows125XReaders()
|
||||
{
|
||||
$charsets = array();
|
||||
foreach (range(0, 8) as $number) {
|
||||
$charsets[] = 'windows-125'.$number;
|
||||
$charsets[] = 'windows125'.$number;
|
||||
$charsets[] = 'WINDOWS-125'.$number;
|
||||
$charsets[] = 'WINDOWS125'.$number;
|
||||
}
|
||||
|
||||
foreach ($charsets as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(1, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingCodePageReaders()
|
||||
{
|
||||
$charsets = array();
|
||||
foreach (range(0, 8) as $number) {
|
||||
$charsets[] = 'cp-125'.$number;
|
||||
$charsets[] = 'cp125'.$number;
|
||||
$charsets[] = 'CP-125'.$number;
|
||||
$charsets[] = 'CP125'.$number;
|
||||
}
|
||||
|
||||
foreach (array(437, 737, 850, 855, 857, 858, 860,
|
||||
861, 863, 865, 866, 869, ) as $number) {
|
||||
$charsets[] = 'cp-'.$number;
|
||||
$charsets[] = 'cp'.$number;
|
||||
$charsets[] = 'CP-'.$number;
|
||||
$charsets[] = 'CP'.$number;
|
||||
}
|
||||
|
||||
foreach ($charsets as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(1, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingAnsiReader()
|
||||
{
|
||||
foreach (array('ansi', 'ANSI') as $ansi) {
|
||||
$reader = $this->_factory->getReaderFor($ansi);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(1, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingMacintoshReader()
|
||||
{
|
||||
foreach (array('macintosh', 'MACINTOSH') as $mac) {
|
||||
$reader = $this->_factory->getReaderFor($mac);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(1, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingKOIReaders()
|
||||
{
|
||||
$charsets = array();
|
||||
foreach (array('7', '8-r', '8-u', '8u', '8r') as $end) {
|
||||
$charsets[] = 'koi-'.$end;
|
||||
$charsets[] = 'koi'.$end;
|
||||
$charsets[] = 'KOI-'.$end;
|
||||
$charsets[] = 'KOI'.$end;
|
||||
}
|
||||
|
||||
foreach ($charsets as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(1, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingIsciiReaders()
|
||||
{
|
||||
foreach (array('iscii', 'ISCII', 'viscii', 'VISCII') as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(1, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingMIKReader()
|
||||
{
|
||||
foreach (array('mik', 'MIK') as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(1, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingCorkReader()
|
||||
{
|
||||
foreach (array('cork', 'CORK', 't1', 'T1') as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(1, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingUcs2Reader()
|
||||
{
|
||||
foreach (array('ucs-2', 'UCS-2', 'ucs2', 'UCS2') as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(2, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingUtf16Reader()
|
||||
{
|
||||
foreach (array('utf-16', 'UTF-16', 'utf16', 'UTF16') as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(2, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingUcs4Reader()
|
||||
{
|
||||
foreach (array('ucs-4', 'UCS-4', 'ucs4', 'UCS4') as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(4, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatingUtf32Reader()
|
||||
{
|
||||
foreach (array('utf-32', 'UTF-32', 'utf32', 'UTF32') as $charset) {
|
||||
$reader = $this->_factory->getReaderFor($charset);
|
||||
$this->assertInstanceOf($this->_prefix.'GenericFixedWidthReader', $reader);
|
||||
$this->assertEquals(4, $reader->getInitialByteSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'swift_required.php';
|
||||
|
||||
//This is more of a "cross your fingers and hope it works" test!
|
||||
|
||||
class Swift_DependencyContainerAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testNoLookupsFail()
|
||||
{
|
||||
$di = Swift_DependencyContainer::getInstance();
|
||||
foreach ($di->listItems() as $itemName) {
|
||||
try {
|
||||
// to be removed in 6.0
|
||||
if ('transport.mail' === $itemName) {
|
||||
continue;
|
||||
}
|
||||
$di->lookup($itemName);
|
||||
} catch (Swift_DependencyException $e) {
|
||||
$this->fail($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'swift_required.php';
|
||||
require_once __DIR__.'/Mime/EmbeddedFileAcceptanceTest.php';
|
||||
|
||||
class Swift_EmbeddedFileAcceptanceTest extends Swift_Mime_EmbeddedFileAcceptanceTest
|
||||
{
|
||||
protected function _createEmbeddedFile()
|
||||
{
|
||||
return Swift_EmbeddedFile::newInstance();
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Encoder_Base64EncoderAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_samplesDir;
|
||||
private $_encoder;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_samplesDir = realpath(__DIR__.'/../../../_samples/charsets');
|
||||
$this->_encoder = new Swift_Encoder_Base64Encoder();
|
||||
}
|
||||
|
||||
public function testEncodingAndDecodingSamples()
|
||||
{
|
||||
$sampleFp = opendir($this->_samplesDir);
|
||||
while (false !== $encodingDir = readdir($sampleFp)) {
|
||||
if (substr($encodingDir, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sampleDir = $this->_samplesDir.'/'.$encodingDir;
|
||||
|
||||
if (is_dir($sampleDir)) {
|
||||
$fileFp = opendir($sampleDir);
|
||||
while (false !== $sampleFile = readdir($fileFp)) {
|
||||
if (substr($sampleFile, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = file_get_contents($sampleDir.'/'.$sampleFile);
|
||||
$encodedText = $this->_encoder->encodeString($text);
|
||||
|
||||
$this->assertEquals(
|
||||
base64_decode($encodedText), $text,
|
||||
'%s: Encoded string should decode back to original string for sample '.
|
||||
$sampleDir.'/'.$sampleFile
|
||||
);
|
||||
}
|
||||
closedir($fileFp);
|
||||
}
|
||||
}
|
||||
closedir($sampleFp);
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Encoder_QpEncoderAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_samplesDir;
|
||||
private $_factory;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_samplesDir = realpath(__DIR__.'/../../../_samples/charsets');
|
||||
$this->_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
|
||||
}
|
||||
|
||||
public function testEncodingAndDecodingSamples()
|
||||
{
|
||||
$sampleFp = opendir($this->_samplesDir);
|
||||
while (false !== $encodingDir = readdir($sampleFp)) {
|
||||
if (substr($encodingDir, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$encoding = $encodingDir;
|
||||
$charStream = new Swift_CharacterStream_ArrayCharacterStream(
|
||||
$this->_factory, $encoding);
|
||||
$encoder = new Swift_Encoder_QpEncoder($charStream);
|
||||
|
||||
$sampleDir = $this->_samplesDir.'/'.$encodingDir;
|
||||
|
||||
if (is_dir($sampleDir)) {
|
||||
$fileFp = opendir($sampleDir);
|
||||
while (false !== $sampleFile = readdir($fileFp)) {
|
||||
if (substr($sampleFile, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = file_get_contents($sampleDir.'/'.$sampleFile);
|
||||
$encodedText = $encoder->encodeString($text);
|
||||
|
||||
foreach (explode("\r\n", $encodedText) as $line) {
|
||||
$this->assertLessThanOrEqual(76, strlen($line));
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
quoted_printable_decode($encodedText), $text,
|
||||
'%s: Encoded string should decode back to original string for sample '.
|
||||
$sampleDir.'/'.$sampleFile
|
||||
);
|
||||
}
|
||||
closedir($fileFp);
|
||||
}
|
||||
}
|
||||
closedir($sampleFp);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Encoder_Rfc2231EncoderAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_samplesDir;
|
||||
private $_factory;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_samplesDir = realpath(__DIR__.'/../../../_samples/charsets');
|
||||
$this->_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
|
||||
}
|
||||
|
||||
public function testEncodingAndDecodingSamples()
|
||||
{
|
||||
$sampleFp = opendir($this->_samplesDir);
|
||||
while (false !== $encodingDir = readdir($sampleFp)) {
|
||||
if (substr($encodingDir, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$encoding = $encodingDir;
|
||||
$charStream = new Swift_CharacterStream_ArrayCharacterStream(
|
||||
$this->_factory, $encoding);
|
||||
$encoder = new Swift_Encoder_Rfc2231Encoder($charStream);
|
||||
|
||||
$sampleDir = $this->_samplesDir.'/'.$encodingDir;
|
||||
|
||||
if (is_dir($sampleDir)) {
|
||||
$fileFp = opendir($sampleDir);
|
||||
while (false !== $sampleFile = readdir($fileFp)) {
|
||||
if (substr($sampleFile, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = file_get_contents($sampleDir.'/'.$sampleFile);
|
||||
$encodedText = $encoder->encodeString($text);
|
||||
|
||||
$this->assertEquals(
|
||||
urldecode(implode('', explode("\r\n", $encodedText))), $text,
|
||||
'%s: Encoded string should decode back to original string for sample '.
|
||||
$sampleDir.'/'.$sampleFile
|
||||
);
|
||||
}
|
||||
closedir($fileFp);
|
||||
}
|
||||
}
|
||||
closedir($sampleFp);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'swift_required.php';
|
||||
|
||||
class Swift_EncodingAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testGet7BitEncodingReturns7BitEncoder()
|
||||
{
|
||||
$encoder = Swift_Encoding::get7BitEncoding();
|
||||
$this->assertEquals('7bit', $encoder->getName());
|
||||
}
|
||||
|
||||
public function testGet8BitEncodingReturns8BitEncoder()
|
||||
{
|
||||
$encoder = Swift_Encoding::get8BitEncoding();
|
||||
$this->assertEquals('8bit', $encoder->getName());
|
||||
}
|
||||
|
||||
public function testGetQpEncodingReturnsQpEncoder()
|
||||
{
|
||||
$encoder = Swift_Encoding::getQpEncoding();
|
||||
$this->assertEquals('quoted-printable', $encoder->getName());
|
||||
}
|
||||
|
||||
public function testGetBase64EncodingReturnsBase64Encoder()
|
||||
{
|
||||
$encoder = Swift_Encoding::getBase64Encoding();
|
||||
$this->assertEquals('base64', $encoder->getName());
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_KeyCache_ArrayKeyCacheAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_cache;
|
||||
private $_key1 = 'key1';
|
||||
private $_key2 = 'key2';
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_cache = new Swift_KeyCache_ArrayKeyCache(
|
||||
new Swift_KeyCache_SimpleKeyCacheInputStream()
|
||||
);
|
||||
}
|
||||
|
||||
public function testStringDataCanBeSetAndFetched()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testStringDataCanBeOverwritten()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'whatever', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertEquals('whatever', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testStringDataCanBeAppended()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'ing', Swift_KeyCache::MODE_APPEND
|
||||
);
|
||||
$this->assertEquals('testing', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testHasKeyReturnValue()
|
||||
{
|
||||
$this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testNsKeyIsWellPartitioned()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->_cache->setString(
|
||||
$this->_key2, 'foo', 'ing', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
|
||||
$this->assertEquals('ing', $this->_cache->getString($this->_key2, 'foo'));
|
||||
}
|
||||
|
||||
public function testItemKeyIsWellPartitioned()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'bar', 'ing', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
|
||||
$this->assertEquals('ing', $this->_cache->getString($this->_key1, 'bar'));
|
||||
}
|
||||
|
||||
public function testByteStreamCanBeImported()
|
||||
{
|
||||
$os = new Swift_ByteStream_ArrayByteStream();
|
||||
$os->write('abcdef');
|
||||
|
||||
$this->_cache->importFromByteStream(
|
||||
$this->_key1, 'foo', $os, Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertEquals('abcdef', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testByteStreamCanBeAppended()
|
||||
{
|
||||
$os1 = new Swift_ByteStream_ArrayByteStream();
|
||||
$os1->write('abcdef');
|
||||
|
||||
$os2 = new Swift_ByteStream_ArrayByteStream();
|
||||
$os2->write('xyzuvw');
|
||||
|
||||
$this->_cache->importFromByteStream(
|
||||
$this->_key1, 'foo', $os1, Swift_KeyCache::MODE_APPEND
|
||||
);
|
||||
$this->_cache->importFromByteStream(
|
||||
$this->_key1, 'foo', $os2, Swift_KeyCache::MODE_APPEND
|
||||
);
|
||||
|
||||
$this->assertEquals('abcdefxyzuvw', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testByteStreamAndStringCanBeAppended()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_APPEND
|
||||
);
|
||||
|
||||
$os = new Swift_ByteStream_ArrayByteStream();
|
||||
$os->write('abcdef');
|
||||
|
||||
$this->_cache->importFromByteStream(
|
||||
$this->_key1, 'foo', $os, Swift_KeyCache::MODE_APPEND
|
||||
);
|
||||
$this->assertEquals('testabcdef', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testDataCanBeExportedToByteStream()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
|
||||
$is = new Swift_ByteStream_ArrayByteStream();
|
||||
|
||||
$this->_cache->exportToByteStream($this->_key1, 'foo', $is);
|
||||
|
||||
$string = '';
|
||||
while (false !== $bytes = $is->read(8192)) {
|
||||
$string .= $bytes;
|
||||
}
|
||||
|
||||
$this->assertEquals('test', $string);
|
||||
}
|
||||
|
||||
public function testKeyCanBeCleared()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
$this->_cache->clearKey($this->_key1, 'foo');
|
||||
$this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testNsKeyCanBeCleared()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'bar', 'xyz', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
$this->assertTrue($this->_cache->hasKey($this->_key1, 'bar'));
|
||||
$this->_cache->clearAll($this->_key1);
|
||||
$this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
$this->assertFalse($this->_cache->hasKey($this->_key1, 'bar'));
|
||||
}
|
||||
|
||||
public function testKeyCacheInputStream()
|
||||
{
|
||||
$is = $this->_cache->getInputByteStream($this->_key1, 'foo');
|
||||
$is->write('abc');
|
||||
$is->write('xyz');
|
||||
$this->assertEquals('abcxyz', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_KeyCache_DiskKeyCacheAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_cache;
|
||||
private $_key1;
|
||||
private $_key2;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_key1 = uniqid(microtime(true), true);
|
||||
$this->_key2 = uniqid(microtime(true), true);
|
||||
$this->_cache = new Swift_KeyCache_DiskKeyCache(new Swift_KeyCache_SimpleKeyCacheInputStream(), sys_get_temp_dir());
|
||||
}
|
||||
|
||||
public function testStringDataCanBeSetAndFetched()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testStringDataCanBeOverwritten()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'whatever', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertEquals('whatever', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testStringDataCanBeAppended()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'ing', Swift_KeyCache::MODE_APPEND
|
||||
);
|
||||
$this->assertEquals('testing', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testHasKeyReturnValue()
|
||||
{
|
||||
$this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testNsKeyIsWellPartitioned()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->_cache->setString(
|
||||
$this->_key2, 'foo', 'ing', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
|
||||
$this->assertEquals('ing', $this->_cache->getString($this->_key2, 'foo'));
|
||||
}
|
||||
|
||||
public function testItemKeyIsWellPartitioned()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'bar', 'ing', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
|
||||
$this->assertEquals('ing', $this->_cache->getString($this->_key1, 'bar'));
|
||||
}
|
||||
|
||||
public function testByteStreamCanBeImported()
|
||||
{
|
||||
$os = new Swift_ByteStream_ArrayByteStream();
|
||||
$os->write('abcdef');
|
||||
|
||||
$this->_cache->importFromByteStream(
|
||||
$this->_key1, 'foo', $os, Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertEquals('abcdef', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testByteStreamCanBeAppended()
|
||||
{
|
||||
$os1 = new Swift_ByteStream_ArrayByteStream();
|
||||
$os1->write('abcdef');
|
||||
|
||||
$os2 = new Swift_ByteStream_ArrayByteStream();
|
||||
$os2->write('xyzuvw');
|
||||
|
||||
$this->_cache->importFromByteStream(
|
||||
$this->_key1, 'foo', $os1, Swift_KeyCache::MODE_APPEND
|
||||
);
|
||||
$this->_cache->importFromByteStream(
|
||||
$this->_key1, 'foo', $os2, Swift_KeyCache::MODE_APPEND
|
||||
);
|
||||
|
||||
$this->assertEquals('abcdefxyzuvw', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testByteStreamAndStringCanBeAppended()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_APPEND
|
||||
);
|
||||
|
||||
$os = new Swift_ByteStream_ArrayByteStream();
|
||||
$os->write('abcdef');
|
||||
|
||||
$this->_cache->importFromByteStream(
|
||||
$this->_key1, 'foo', $os, Swift_KeyCache::MODE_APPEND
|
||||
);
|
||||
$this->assertEquals('testabcdef', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testDataCanBeExportedToByteStream()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
|
||||
$is = new Swift_ByteStream_ArrayByteStream();
|
||||
|
||||
$this->_cache->exportToByteStream($this->_key1, 'foo', $is);
|
||||
|
||||
$string = '';
|
||||
while (false !== $bytes = $is->read(8192)) {
|
||||
$string .= $bytes;
|
||||
}
|
||||
|
||||
$this->assertEquals('test', $string);
|
||||
}
|
||||
|
||||
public function testKeyCanBeCleared()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
$this->_cache->clearKey($this->_key1, 'foo');
|
||||
$this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
}
|
||||
|
||||
public function testNsKeyCanBeCleared()
|
||||
{
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->_cache->setString(
|
||||
$this->_key1, 'bar', 'xyz', Swift_KeyCache::MODE_WRITE
|
||||
);
|
||||
$this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
$this->assertTrue($this->_cache->hasKey($this->_key1, 'bar'));
|
||||
$this->_cache->clearAll($this->_key1);
|
||||
$this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
|
||||
$this->assertFalse($this->_cache->hasKey($this->_key1, 'bar'));
|
||||
}
|
||||
|
||||
public function testKeyCacheInputStream()
|
||||
{
|
||||
$is = $this->_cache->getInputByteStream($this->_key1, 'foo');
|
||||
$is->write('abc');
|
||||
$is->write('xyz');
|
||||
$this->assertEquals('abcxyz', $this->_cache->getString($this->_key1, 'foo'));
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'swift_required.php';
|
||||
require_once __DIR__.'/Mime/SimpleMessageAcceptanceTest.php';
|
||||
|
||||
class Swift_MessageAcceptanceTest extends Swift_Mime_SimpleMessageAcceptanceTest
|
||||
{
|
||||
public function testAddPartWrapper()
|
||||
{
|
||||
$message = $this->_createMessage();
|
||||
$message->setSubject('just a test subject');
|
||||
$message->setFrom(array(
|
||||
'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
|
||||
|
||||
$id = $message->getId();
|
||||
$date = $message->getDate();
|
||||
$boundary = $message->getBoundary();
|
||||
|
||||
$message->addPart('foo', 'text/plain', 'iso-8859-1');
|
||||
$message->addPart('test <b>foo</b>', 'text/html', 'iso-8859-1');
|
||||
|
||||
$this->assertEquals(
|
||||
'Message-ID: <'.$id.'>'."\r\n".
|
||||
'Date: '.date('r', $date)."\r\n".
|
||||
'Subject: just a test subject'."\r\n".
|
||||
'From: Chris Corbyn <chris.corbyn@swiftmailer.org>'."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: multipart/alternative;'."\r\n".
|
||||
' boundary="'.$boundary.'"'."\r\n".
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: text/plain; charset=iso-8859-1'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'foo'.
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: text/html; charset=iso-8859-1'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'test <b>foo</b>'.
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary.'--'."\r\n",
|
||||
$message->toString()
|
||||
);
|
||||
}
|
||||
|
||||
protected function _createMessage()
|
||||
{
|
||||
Swift_DependencyContainer::getInstance()
|
||||
->register('properties.charset')->asValue(null);
|
||||
|
||||
return Swift_Message::newInstance();
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Mime_AttachmentAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_contentEncoder;
|
||||
private $_cache;
|
||||
private $_grammar;
|
||||
private $_headers;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_cache = new Swift_KeyCache_ArrayKeyCache(
|
||||
new Swift_KeyCache_SimpleKeyCacheInputStream()
|
||||
);
|
||||
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
|
||||
$this->_contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
|
||||
|
||||
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
|
||||
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
|
||||
);
|
||||
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(
|
||||
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
|
||||
);
|
||||
$this->_grammar = new Swift_Mime_Grammar();
|
||||
$this->_headers = new Swift_Mime_SimpleHeaderSet(
|
||||
new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $this->_grammar)
|
||||
);
|
||||
}
|
||||
|
||||
public function testDispositionIsSetInHeader()
|
||||
{
|
||||
$attachment = $this->_createAttachment();
|
||||
$attachment->setContentType('application/pdf');
|
||||
$attachment->setDisposition('inline');
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-Disposition: inline'."\r\n",
|
||||
$attachment->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testDispositionIsAttachmentByDefault()
|
||||
{
|
||||
$attachment = $this->_createAttachment();
|
||||
$attachment->setContentType('application/pdf');
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-Disposition: attachment'."\r\n",
|
||||
$attachment->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testFilenameIsSetInHeader()
|
||||
{
|
||||
$attachment = $this->_createAttachment();
|
||||
$attachment->setContentType('application/pdf');
|
||||
$attachment->setFilename('foo.pdf');
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf; name=foo.pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-Disposition: attachment; filename=foo.pdf'."\r\n",
|
||||
$attachment->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testSizeIsSetInHeader()
|
||||
{
|
||||
$attachment = $this->_createAttachment();
|
||||
$attachment->setContentType('application/pdf');
|
||||
$attachment->setSize(12340);
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-Disposition: attachment; size=12340'."\r\n",
|
||||
$attachment->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testMultipleParametersInHeader()
|
||||
{
|
||||
$attachment = $this->_createAttachment();
|
||||
$attachment->setContentType('application/pdf');
|
||||
$attachment->setFilename('foo.pdf');
|
||||
$attachment->setSize(12340);
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf; name=foo.pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-Disposition: attachment; filename=foo.pdf; size=12340'."\r\n",
|
||||
$attachment->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testEndToEnd()
|
||||
{
|
||||
$attachment = $this->_createAttachment();
|
||||
$attachment->setContentType('application/pdf');
|
||||
$attachment->setFilename('foo.pdf');
|
||||
$attachment->setSize(12340);
|
||||
$attachment->setBody('abcd');
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf; name=foo.pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-Disposition: attachment; filename=foo.pdf; size=12340'."\r\n".
|
||||
"\r\n".
|
||||
base64_encode('abcd'),
|
||||
$attachment->toString()
|
||||
);
|
||||
}
|
||||
|
||||
protected function _createAttachment()
|
||||
{
|
||||
$entity = new Swift_Mime_Attachment(
|
||||
$this->_headers,
|
||||
$this->_contentEncoder,
|
||||
$this->_cache,
|
||||
$this->_grammar
|
||||
);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Mime_ContentEncoder_Base64ContentEncoderAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_samplesDir;
|
||||
private $_encoder;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_samplesDir = realpath(__DIR__.'/../../../../_samples/charsets');
|
||||
$this->_encoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
|
||||
}
|
||||
|
||||
public function testEncodingAndDecodingSamples()
|
||||
{
|
||||
$sampleFp = opendir($this->_samplesDir);
|
||||
while (false !== $encodingDir = readdir($sampleFp)) {
|
||||
if (substr($encodingDir, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sampleDir = $this->_samplesDir.'/'.$encodingDir;
|
||||
|
||||
if (is_dir($sampleDir)) {
|
||||
$fileFp = opendir($sampleDir);
|
||||
while (false !== $sampleFile = readdir($fileFp)) {
|
||||
if (substr($sampleFile, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = file_get_contents($sampleDir.'/'.$sampleFile);
|
||||
|
||||
$os = new Swift_ByteStream_ArrayByteStream();
|
||||
$os->write($text);
|
||||
|
||||
$is = new Swift_ByteStream_ArrayByteStream();
|
||||
|
||||
$this->_encoder->encodeByteStream($os, $is);
|
||||
|
||||
$encoded = '';
|
||||
while (false !== $bytes = $is->read(8192)) {
|
||||
$encoded .= $bytes;
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
base64_decode($encoded), $text,
|
||||
'%s: Encoded string should decode back to original string for sample '.
|
||||
$sampleDir.'/'.$sampleFile
|
||||
);
|
||||
}
|
||||
closedir($fileFp);
|
||||
}
|
||||
}
|
||||
closedir($sampleFp);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Mime_ContentEncoder_NativeQpContentEncoderAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $_samplesDir;
|
||||
|
||||
/**
|
||||
* @var Swift_Mime_ContentEncoder_NativeQpContentEncoder
|
||||
*/
|
||||
protected $_encoder;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_samplesDir = realpath(__DIR__.'/../../../../_samples/charsets');
|
||||
$this->_encoder = new Swift_Mime_ContentEncoder_NativeQpContentEncoder();
|
||||
}
|
||||
|
||||
public function testEncodingAndDecodingSamples()
|
||||
{
|
||||
$sampleFp = opendir($this->_samplesDir);
|
||||
while (false !== $encodingDir = readdir($sampleFp)) {
|
||||
if (substr($encodingDir, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sampleDir = $this->_samplesDir.'/'.$encodingDir;
|
||||
|
||||
if (is_dir($sampleDir)) {
|
||||
$fileFp = opendir($sampleDir);
|
||||
while (false !== $sampleFile = readdir($fileFp)) {
|
||||
if (substr($sampleFile, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = file_get_contents($sampleDir.'/'.$sampleFile);
|
||||
|
||||
$os = new Swift_ByteStream_ArrayByteStream();
|
||||
$os->write($text);
|
||||
|
||||
$is = new Swift_ByteStream_ArrayByteStream();
|
||||
$this->_encoder->encodeByteStream($os, $is);
|
||||
|
||||
$encoded = '';
|
||||
while (false !== $bytes = $is->read(8192)) {
|
||||
$encoded .= $bytes;
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
quoted_printable_decode($encoded),
|
||||
// CR and LF are converted to CRLF
|
||||
preg_replace('~\r(?!\n)|(?<!\r)\n~', "\r\n", $text),
|
||||
'%s: Encoded string should decode back to original string for sample '.$sampleDir.'/'.$sampleFile
|
||||
);
|
||||
}
|
||||
closedir($fileFp);
|
||||
}
|
||||
}
|
||||
closedir($sampleFp);
|
||||
}
|
||||
|
||||
public function testEncodingAndDecodingSamplesFromDiConfiguredInstance()
|
||||
{
|
||||
$encoder = $this->_createEncoderFromContainer();
|
||||
$this->assertSame('=C3=A4=C3=B6=C3=BC=C3=9F', $encoder->encodeString('äöüß'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testCharsetChangeNotImplemented()
|
||||
{
|
||||
$this->_encoder->charsetChanged('utf-8');
|
||||
$this->_encoder->charsetChanged('charset');
|
||||
$this->_encoder->encodeString('foo');
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$this->assertSame('quoted-printable', $this->_encoder->getName());
|
||||
}
|
||||
|
||||
private function _createEncoderFromContainer()
|
||||
{
|
||||
return Swift_DependencyContainer::getInstance()
|
||||
->lookup('mime.nativeqpcontentencoder')
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Mime_ContentEncoder_PlainContentEncoderAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_samplesDir;
|
||||
private $_encoder;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_samplesDir = realpath(__DIR__.'/../../../../_samples/charsets');
|
||||
$this->_encoder = new Swift_Mime_ContentEncoder_PlainContentEncoder('8bit');
|
||||
}
|
||||
|
||||
public function testEncodingAndDecodingSamplesString()
|
||||
{
|
||||
$sampleFp = opendir($this->_samplesDir);
|
||||
while (false !== $encodingDir = readdir($sampleFp)) {
|
||||
if (substr($encodingDir, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sampleDir = $this->_samplesDir.'/'.$encodingDir;
|
||||
|
||||
if (is_dir($sampleDir)) {
|
||||
$fileFp = opendir($sampleDir);
|
||||
while (false !== $sampleFile = readdir($fileFp)) {
|
||||
if (substr($sampleFile, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = file_get_contents($sampleDir.'/'.$sampleFile);
|
||||
$encodedText = $this->_encoder->encodeString($text);
|
||||
|
||||
$this->assertEquals(
|
||||
$encodedText, $text,
|
||||
'%s: Encoded string should be identical to original string for sample '.
|
||||
$sampleDir.'/'.$sampleFile
|
||||
);
|
||||
}
|
||||
closedir($fileFp);
|
||||
}
|
||||
}
|
||||
closedir($sampleFp);
|
||||
}
|
||||
|
||||
public function testEncodingAndDecodingSamplesByteStream()
|
||||
{
|
||||
$sampleFp = opendir($this->_samplesDir);
|
||||
while (false !== $encodingDir = readdir($sampleFp)) {
|
||||
if (substr($encodingDir, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sampleDir = $this->_samplesDir.'/'.$encodingDir;
|
||||
|
||||
if (is_dir($sampleDir)) {
|
||||
$fileFp = opendir($sampleDir);
|
||||
while (false !== $sampleFile = readdir($fileFp)) {
|
||||
if (substr($sampleFile, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = file_get_contents($sampleDir.'/'.$sampleFile);
|
||||
|
||||
$os = new Swift_ByteStream_ArrayByteStream();
|
||||
$os->write($text);
|
||||
|
||||
$is = new Swift_ByteStream_ArrayByteStream();
|
||||
|
||||
$this->_encoder->encodeByteStream($os, $is);
|
||||
|
||||
$encoded = '';
|
||||
while (false !== $bytes = $is->read(8192)) {
|
||||
$encoded .= $bytes;
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
$encoded, $text,
|
||||
'%s: Encoded string should be identical to original string for sample '.
|
||||
$sampleDir.'/'.$sampleFile
|
||||
);
|
||||
}
|
||||
closedir($fileFp);
|
||||
}
|
||||
}
|
||||
closedir($sampleFp);
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Mime_ContentEncoder_QpContentEncoderAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_samplesDir;
|
||||
private $_factory;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_samplesDir = realpath(__DIR__.'/../../../../_samples/charsets');
|
||||
$this->_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
Swift_Preferences::getInstance()->setQPDotEscape(false);
|
||||
}
|
||||
|
||||
public function testEncodingAndDecodingSamples()
|
||||
{
|
||||
$sampleFp = opendir($this->_samplesDir);
|
||||
while (false !== $encodingDir = readdir($sampleFp)) {
|
||||
if (substr($encodingDir, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$encoding = $encodingDir;
|
||||
$charStream = new Swift_CharacterStream_NgCharacterStream(
|
||||
$this->_factory, $encoding);
|
||||
$encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
|
||||
|
||||
$sampleDir = $this->_samplesDir.'/'.$encodingDir;
|
||||
|
||||
if (is_dir($sampleDir)) {
|
||||
$fileFp = opendir($sampleDir);
|
||||
while (false !== $sampleFile = readdir($fileFp)) {
|
||||
if (substr($sampleFile, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = file_get_contents($sampleDir.'/'.$sampleFile);
|
||||
|
||||
$os = new Swift_ByteStream_ArrayByteStream();
|
||||
$os->write($text);
|
||||
|
||||
$is = new Swift_ByteStream_ArrayByteStream();
|
||||
$encoder->encodeByteStream($os, $is);
|
||||
|
||||
$encoded = '';
|
||||
while (false !== $bytes = $is->read(8192)) {
|
||||
$encoded .= $bytes;
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
quoted_printable_decode($encoded), $text,
|
||||
'%s: Encoded string should decode back to original string for sample '.
|
||||
$sampleDir.'/'.$sampleFile
|
||||
);
|
||||
}
|
||||
closedir($fileFp);
|
||||
}
|
||||
}
|
||||
closedir($sampleFp);
|
||||
}
|
||||
|
||||
public function testEncodingAndDecodingSamplesFromDiConfiguredInstance()
|
||||
{
|
||||
$sampleFp = opendir($this->_samplesDir);
|
||||
while (false !== $encodingDir = readdir($sampleFp)) {
|
||||
if (substr($encodingDir, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$encoding = $encodingDir;
|
||||
$encoder = $this->_createEncoderFromContainer();
|
||||
|
||||
$sampleDir = $this->_samplesDir.'/'.$encodingDir;
|
||||
|
||||
if (is_dir($sampleDir)) {
|
||||
$fileFp = opendir($sampleDir);
|
||||
while (false !== $sampleFile = readdir($fileFp)) {
|
||||
if (substr($sampleFile, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = file_get_contents($sampleDir.'/'.$sampleFile);
|
||||
|
||||
$os = new Swift_ByteStream_ArrayByteStream();
|
||||
$os->write($text);
|
||||
|
||||
$is = new Swift_ByteStream_ArrayByteStream();
|
||||
$encoder->encodeByteStream($os, $is);
|
||||
|
||||
$encoded = '';
|
||||
while (false !== $bytes = $is->read(8192)) {
|
||||
$encoded .= $bytes;
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
str_replace("\r\n", "\n", quoted_printable_decode($encoded)), str_replace("\r\n", "\n", $text),
|
||||
'%s: Encoded string should decode back to original string for sample '.
|
||||
$sampleDir.'/'.$sampleFile
|
||||
);
|
||||
}
|
||||
closedir($fileFp);
|
||||
}
|
||||
}
|
||||
closedir($sampleFp);
|
||||
}
|
||||
|
||||
public function testEncodingLFTextWithDiConfiguredInstance()
|
||||
{
|
||||
$encoder = $this->_createEncoderFromContainer();
|
||||
$this->assertEquals("a\r\nb\r\nc", $encoder->encodeString("a\nb\nc"));
|
||||
}
|
||||
|
||||
public function testEncodingCRTextWithDiConfiguredInstance()
|
||||
{
|
||||
$encoder = $this->_createEncoderFromContainer();
|
||||
$this->assertEquals("a\r\nb\r\nc", $encoder->encodeString("a\rb\rc"));
|
||||
}
|
||||
|
||||
public function testEncodingLFCRTextWithDiConfiguredInstance()
|
||||
{
|
||||
$encoder = $this->_createEncoderFromContainer();
|
||||
$this->assertEquals("a\r\n\r\nb\r\n\r\nc", $encoder->encodeString("a\n\rb\n\rc"));
|
||||
}
|
||||
|
||||
public function testEncodingCRLFTextWithDiConfiguredInstance()
|
||||
{
|
||||
$encoder = $this->_createEncoderFromContainer();
|
||||
$this->assertEquals("a\r\nb\r\nc", $encoder->encodeString("a\r\nb\r\nc"));
|
||||
}
|
||||
|
||||
public function testEncodingDotStuffingWithDiConfiguredInstance()
|
||||
{
|
||||
// Enable DotEscaping
|
||||
Swift_Preferences::getInstance()->setQPDotEscape(true);
|
||||
$encoder = $this->_createEncoderFromContainer();
|
||||
$this->assertEquals("a=2E\r\n=2E\r\n=2Eb\r\nc", $encoder->encodeString("a.\r\n.\r\n.b\r\nc"));
|
||||
// Return to default
|
||||
Swift_Preferences::getInstance()->setQPDotEscape(false);
|
||||
$encoder = $this->_createEncoderFromContainer();
|
||||
$this->assertEquals("a.\r\n.\r\n.b\r\nc", $encoder->encodeString("a.\r\n.\r\n.b\r\nc"));
|
||||
}
|
||||
|
||||
public function testDotStuffingEncodingAndDecodingSamplesFromDiConfiguredInstance()
|
||||
{
|
||||
// Enable DotEscaping
|
||||
Swift_Preferences::getInstance()->setQPDotEscape(true);
|
||||
$this->testEncodingAndDecodingSamplesFromDiConfiguredInstance();
|
||||
}
|
||||
|
||||
private function _createEncoderFromContainer()
|
||||
{
|
||||
return Swift_DependencyContainer::getInstance()
|
||||
->lookup('mime.qpcontentencoder')
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Mime_EmbeddedFileAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_contentEncoder;
|
||||
private $_cache;
|
||||
private $_grammar;
|
||||
private $_headers;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_cache = new Swift_KeyCache_ArrayKeyCache(
|
||||
new Swift_KeyCache_SimpleKeyCacheInputStream()
|
||||
);
|
||||
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
|
||||
$this->_contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
|
||||
|
||||
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
|
||||
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
|
||||
);
|
||||
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(
|
||||
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
|
||||
);
|
||||
$this->_grammar = new Swift_Mime_Grammar();
|
||||
$this->_headers = new Swift_Mime_SimpleHeaderSet(
|
||||
new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $this->_grammar)
|
||||
);
|
||||
}
|
||||
|
||||
public function testContentIdIsSetInHeader()
|
||||
{
|
||||
$file = $this->_createEmbeddedFile();
|
||||
$file->setContentType('application/pdf');
|
||||
$file->setId('foo@bar');
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-ID: <foo@bar>'."\r\n".
|
||||
'Content-Disposition: inline'."\r\n",
|
||||
$file->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testDispositionIsSetInHeader()
|
||||
{
|
||||
$file = $this->_createEmbeddedFile();
|
||||
$id = $file->getId();
|
||||
$file->setContentType('application/pdf');
|
||||
$file->setDisposition('attachment');
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-ID: <'.$id.'>'."\r\n".
|
||||
'Content-Disposition: attachment'."\r\n",
|
||||
$file->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testFilenameIsSetInHeader()
|
||||
{
|
||||
$file = $this->_createEmbeddedFile();
|
||||
$id = $file->getId();
|
||||
$file->setContentType('application/pdf');
|
||||
$file->setFilename('foo.pdf');
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf; name=foo.pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-ID: <'.$id.'>'."\r\n".
|
||||
'Content-Disposition: inline; filename=foo.pdf'."\r\n",
|
||||
$file->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testSizeIsSetInHeader()
|
||||
{
|
||||
$file = $this->_createEmbeddedFile();
|
||||
$id = $file->getId();
|
||||
$file->setContentType('application/pdf');
|
||||
$file->setSize(12340);
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-ID: <'.$id.'>'."\r\n".
|
||||
'Content-Disposition: inline; size=12340'."\r\n",
|
||||
$file->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testMultipleParametersInHeader()
|
||||
{
|
||||
$file = $this->_createEmbeddedFile();
|
||||
$id = $file->getId();
|
||||
$file->setContentType('application/pdf');
|
||||
$file->setFilename('foo.pdf');
|
||||
$file->setSize(12340);
|
||||
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf; name=foo.pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-ID: <'.$id.'>'."\r\n".
|
||||
'Content-Disposition: inline; filename=foo.pdf; size=12340'."\r\n",
|
||||
$file->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testEndToEnd()
|
||||
{
|
||||
$file = $this->_createEmbeddedFile();
|
||||
$id = $file->getId();
|
||||
$file->setContentType('application/pdf');
|
||||
$file->setFilename('foo.pdf');
|
||||
$file->setSize(12340);
|
||||
$file->setBody('abcd');
|
||||
$this->assertEquals(
|
||||
'Content-Type: application/pdf; name=foo.pdf'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-ID: <'.$id.'>'."\r\n".
|
||||
'Content-Disposition: inline; filename=foo.pdf; size=12340'."\r\n".
|
||||
"\r\n".
|
||||
base64_encode('abcd'),
|
||||
$file->toString()
|
||||
);
|
||||
}
|
||||
|
||||
protected function _createEmbeddedFile()
|
||||
{
|
||||
$entity = new Swift_Mime_EmbeddedFile(
|
||||
$this->_headers,
|
||||
$this->_contentEncoder,
|
||||
$this->_cache,
|
||||
$this->_grammar
|
||||
);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Mime_HeaderEncoder_Base64HeaderEncoderAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_encoder;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_encoder = new Swift_Mime_HeaderEncoder_Base64HeaderEncoder();
|
||||
}
|
||||
|
||||
public function testEncodingJIS()
|
||||
{
|
||||
if (function_exists('mb_convert_encoding')) {
|
||||
// base64_encode and split cannot handle long JIS text to fold
|
||||
$subject = '長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い件名';
|
||||
|
||||
$encodedWrapperLength = strlen('=?iso-2022-jp?'.$this->_encoder->getName().'??=');
|
||||
|
||||
$old = mb_internal_encoding();
|
||||
mb_internal_encoding('utf-8');
|
||||
$newstring = mb_encode_mimeheader($subject, 'iso-2022-jp', 'B', "\r\n");
|
||||
mb_internal_encoding($old);
|
||||
|
||||
$encoded = $this->_encoder->encodeString($subject, 0, 75 - $encodedWrapperLength, 'iso-2022-jp');
|
||||
$this->assertEquals(
|
||||
$encoded, $newstring,
|
||||
'Encoded string should decode back to original string for sample '
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Mime_MimePartAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_contentEncoder;
|
||||
private $_cache;
|
||||
private $_grammar;
|
||||
private $_headers;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_cache = new Swift_KeyCache_ArrayKeyCache(
|
||||
new Swift_KeyCache_SimpleKeyCacheInputStream()
|
||||
);
|
||||
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
|
||||
$this->_contentEncoder = new Swift_Mime_ContentEncoder_QpContentEncoder(
|
||||
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'),
|
||||
new Swift_StreamFilters_ByteArrayReplacementFilter(
|
||||
array(array(0x0D, 0x0A), array(0x0D), array(0x0A)),
|
||||
array(array(0x0A), array(0x0A), array(0x0D, 0x0A))
|
||||
)
|
||||
);
|
||||
|
||||
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
|
||||
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
|
||||
);
|
||||
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(
|
||||
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
|
||||
);
|
||||
$this->_grammar = new Swift_Mime_Grammar();
|
||||
$this->_headers = new Swift_Mime_SimpleHeaderSet(
|
||||
new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $this->_grammar)
|
||||
);
|
||||
}
|
||||
|
||||
public function testCharsetIsSetInHeader()
|
||||
{
|
||||
$part = $this->_createMimePart();
|
||||
$part->setContentType('text/plain');
|
||||
$part->setCharset('utf-8');
|
||||
$part->setBody('foobar');
|
||||
$this->assertEquals(
|
||||
'Content-Type: text/plain; charset=utf-8'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'foobar',
|
||||
$part->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testFormatIsSetInHeaders()
|
||||
{
|
||||
$part = $this->_createMimePart();
|
||||
$part->setContentType('text/plain');
|
||||
$part->setFormat('flowed');
|
||||
$part->setBody('> foobar');
|
||||
$this->assertEquals(
|
||||
'Content-Type: text/plain; format=flowed'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'> foobar',
|
||||
$part->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testDelSpIsSetInHeaders()
|
||||
{
|
||||
$part = $this->_createMimePart();
|
||||
$part->setContentType('text/plain');
|
||||
$part->setDelSp(true);
|
||||
$part->setBody('foobar');
|
||||
$this->assertEquals(
|
||||
'Content-Type: text/plain; delsp=yes'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'foobar',
|
||||
$part->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testAll3ParamsInHeaders()
|
||||
{
|
||||
$part = $this->_createMimePart();
|
||||
$part->setContentType('text/plain');
|
||||
$part->setCharset('utf-8');
|
||||
$part->setFormat('fixed');
|
||||
$part->setDelSp(true);
|
||||
$part->setBody('foobar');
|
||||
$this->assertEquals(
|
||||
'Content-Type: text/plain; charset=utf-8; format=fixed; delsp=yes'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'foobar',
|
||||
$part->toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testBodyIsCanonicalized()
|
||||
{
|
||||
$part = $this->_createMimePart();
|
||||
$part->setContentType('text/plain');
|
||||
$part->setCharset('utf-8');
|
||||
$part->setBody("foobar\r\rtest\ning\r");
|
||||
$this->assertEquals(
|
||||
'Content-Type: text/plain; charset=utf-8'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
"foobar\r\n".
|
||||
"\r\n".
|
||||
"test\r\n".
|
||||
"ing\r\n",
|
||||
$part->toString()
|
||||
);
|
||||
}
|
||||
|
||||
protected function _createMimePart()
|
||||
{
|
||||
$entity = new Swift_Mime_MimePart(
|
||||
$this->_headers,
|
||||
$this->_contentEncoder,
|
||||
$this->_cache,
|
||||
$this->_grammar
|
||||
);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'swift_required.php';
|
||||
require_once __DIR__.'/Mime/MimePartAcceptanceTest.php';
|
||||
|
||||
class Swift_MimePartAcceptanceTest extends Swift_Mime_MimePartAcceptanceTest
|
||||
{
|
||||
protected function _createMimePart()
|
||||
{
|
||||
Swift_DependencyContainer::getInstance()
|
||||
->register('properties.charset')->asValue(null);
|
||||
|
||||
return Swift_MimePart::newInstance();
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
<?php
|
||||
|
||||
abstract class Swift_Transport_StreamBuffer_AbstractStreamBufferAcceptanceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $_buffer;
|
||||
|
||||
abstract protected function _initializeBuffer();
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
if (true == getenv('TRAVIS')) {
|
||||
$this->markTestSkipped(
|
||||
'Will fail on travis-ci if not skipped due to travis blocking '.
|
||||
'socket mailing tcp connections.'
|
||||
);
|
||||
}
|
||||
|
||||
$this->_buffer = new Swift_Transport_StreamBuffer(
|
||||
$this->getMockBuilder('Swift_ReplacementFilterFactory')->getMock()
|
||||
);
|
||||
}
|
||||
|
||||
public function testReadLine()
|
||||
{
|
||||
$this->_initializeBuffer();
|
||||
|
||||
$line = $this->_buffer->readLine(0);
|
||||
$this->assertRegExp('/^[0-9]{3}.*?\r\n$/D', $line);
|
||||
$seq = $this->_buffer->write("QUIT\r\n");
|
||||
$this->assertTrue((bool) $seq);
|
||||
$line = $this->_buffer->readLine($seq);
|
||||
$this->assertRegExp('/^[0-9]{3}.*?\r\n$/D', $line);
|
||||
$this->_buffer->terminate();
|
||||
}
|
||||
|
||||
public function testWrite()
|
||||
{
|
||||
$this->_initializeBuffer();
|
||||
|
||||
$line = $this->_buffer->readLine(0);
|
||||
$this->assertRegExp('/^[0-9]{3}.*?\r\n$/D', $line);
|
||||
|
||||
$seq = $this->_buffer->write("HELO foo\r\n");
|
||||
$this->assertTrue((bool) $seq);
|
||||
$line = $this->_buffer->readLine($seq);
|
||||
$this->assertRegExp('/^[0-9]{3}.*?\r\n$/D', $line);
|
||||
|
||||
$seq = $this->_buffer->write("QUIT\r\n");
|
||||
$this->assertTrue((bool) $seq);
|
||||
$line = $this->_buffer->readLine($seq);
|
||||
$this->assertRegExp('/^[0-9]{3}.*?\r\n$/D', $line);
|
||||
$this->_buffer->terminate();
|
||||
}
|
||||
|
||||
public function testBindingOtherStreamsMirrorsWriteOperations()
|
||||
{
|
||||
$this->_initializeBuffer();
|
||||
|
||||
$is1 = $this->_createMockInputStream();
|
||||
$is2 = $this->_createMockInputStream();
|
||||
|
||||
$is1->expects($this->at(0))
|
||||
->method('write')
|
||||
->with('x');
|
||||
$is1->expects($this->at(1))
|
||||
->method('write')
|
||||
->with('y');
|
||||
$is2->expects($this->at(0))
|
||||
->method('write')
|
||||
->with('x');
|
||||
$is2->expects($this->at(1))
|
||||
->method('write')
|
||||
->with('y');
|
||||
|
||||
$this->_buffer->bind($is1);
|
||||
$this->_buffer->bind($is2);
|
||||
|
||||
$this->_buffer->write('x');
|
||||
$this->_buffer->write('y');
|
||||
}
|
||||
|
||||
public function testBindingOtherStreamsMirrorsFlushOperations()
|
||||
{
|
||||
$this->_initializeBuffer();
|
||||
|
||||
$is1 = $this->_createMockInputStream();
|
||||
$is2 = $this->_createMockInputStream();
|
||||
|
||||
$is1->expects($this->once())
|
||||
->method('flushBuffers');
|
||||
$is2->expects($this->once())
|
||||
->method('flushBuffers');
|
||||
|
||||
$this->_buffer->bind($is1);
|
||||
$this->_buffer->bind($is2);
|
||||
|
||||
$this->_buffer->flushBuffers();
|
||||
}
|
||||
|
||||
public function testUnbindingStreamPreventsFurtherWrites()
|
||||
{
|
||||
$this->_initializeBuffer();
|
||||
|
||||
$is1 = $this->_createMockInputStream();
|
||||
$is2 = $this->_createMockInputStream();
|
||||
|
||||
$is1->expects($this->at(0))
|
||||
->method('write')
|
||||
->with('x');
|
||||
$is1->expects($this->at(1))
|
||||
->method('write')
|
||||
->with('y');
|
||||
$is2->expects($this->once())
|
||||
->method('write')
|
||||
->with('x');
|
||||
|
||||
$this->_buffer->bind($is1);
|
||||
$this->_buffer->bind($is2);
|
||||
|
||||
$this->_buffer->write('x');
|
||||
|
||||
$this->_buffer->unbind($is2);
|
||||
|
||||
$this->_buffer->write('y');
|
||||
}
|
||||
|
||||
private function _createMockInputStream()
|
||||
{
|
||||
return $this->getMockBuilder('Swift_InputByteStream')->getMock();
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__.'/AbstractStreamBufferAcceptanceTest.php';
|
||||
|
||||
class Swift_Transport_StreamBuffer_BasicSocketAcceptanceTest extends Swift_Transport_StreamBuffer_AbstractStreamBufferAcceptanceTest
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
if (!defined('SWIFT_SMTP_HOST')) {
|
||||
$this->markTestSkipped(
|
||||
'Cannot run test without an SMTP host to connect to (define '.
|
||||
'SWIFT_SMTP_HOST in tests/acceptance.conf.php if you wish to run this test)'
|
||||
);
|
||||
}
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
protected function _initializeBuffer()
|
||||
{
|
||||
$parts = explode(':', SWIFT_SMTP_HOST);
|
||||
$host = $parts[0];
|
||||
$port = isset($parts[1]) ? $parts[1] : 25;
|
||||
|
||||
$this->_buffer->initialize(array(
|
||||
'type' => Swift_Transport_IoBuffer::TYPE_SOCKET,
|
||||
'host' => $host,
|
||||
'port' => $port,
|
||||
'protocol' => 'tcp',
|
||||
'blocking' => 1,
|
||||
'timeout' => 15,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__.'/AbstractStreamBufferAcceptanceTest.php';
|
||||
|
||||
class Swift_Transport_StreamBuffer_ProcessAcceptanceTest extends Swift_Transport_StreamBuffer_AbstractStreamBufferAcceptanceTest
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
if (!defined('SWIFT_SENDMAIL_PATH')) {
|
||||
$this->markTestSkipped(
|
||||
'Cannot run test without a path to sendmail (define '.
|
||||
'SWIFT_SENDMAIL_PATH in tests/acceptance.conf.php if you wish to run this test)'
|
||||
);
|
||||
}
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
protected function _initializeBuffer()
|
||||
{
|
||||
$this->_buffer->initialize(array(
|
||||
'type' => Swift_Transport_IoBuffer::TYPE_PROCESS,
|
||||
'command' => SWIFT_SENDMAIL_PATH.' -bs',
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Transport_StreamBuffer_SocketTimeoutTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $_buffer;
|
||||
|
||||
protected $_randomHighPort;
|
||||
|
||||
protected $_server;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
if (!defined('SWIFT_SMTP_HOST')) {
|
||||
$this->markTestSkipped(
|
||||
'Cannot run test without an SMTP host to connect to (define '.
|
||||
'SWIFT_SMTP_HOST in tests/acceptance.conf.php if you wish to run this test)'
|
||||
);
|
||||
}
|
||||
|
||||
$serverStarted = false;
|
||||
for ($i = 0; $i < 5; ++$i) {
|
||||
$this->_randomHighPort = rand(50000, 65000);
|
||||
$this->_server = stream_socket_server('tcp://127.0.0.1:'.$this->_randomHighPort);
|
||||
if ($this->_server) {
|
||||
$serverStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_buffer = new Swift_Transport_StreamBuffer(
|
||||
$this->getMockBuilder('Swift_ReplacementFilterFactory')->getMock()
|
||||
);
|
||||
}
|
||||
|
||||
protected function _initializeBuffer()
|
||||
{
|
||||
$host = '127.0.0.1';
|
||||
$port = $this->_randomHighPort;
|
||||
|
||||
$this->_buffer->initialize(array(
|
||||
'type' => Swift_Transport_IoBuffer::TYPE_SOCKET,
|
||||
'host' => $host,
|
||||
'port' => $port,
|
||||
'protocol' => 'tcp',
|
||||
'blocking' => 1,
|
||||
'timeout' => 1,
|
||||
));
|
||||
}
|
||||
|
||||
public function testTimeoutException()
|
||||
{
|
||||
$this->_initializeBuffer();
|
||||
$e = null;
|
||||
try {
|
||||
$line = $this->_buffer->readLine(0);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
$this->assertInstanceOf('Swift_IoException', $e, 'IO Exception Not Thrown On Connection Timeout');
|
||||
$this->assertRegExp('/Connection to .* Timed Out/', $e->getMessage());
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
if ($this->_server) {
|
||||
stream_socket_shutdown($this->_server, STREAM_SHUT_RDWR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__.'/AbstractStreamBufferAcceptanceTest.php';
|
||||
|
||||
class Swift_Transport_StreamBuffer_SslSocketAcceptanceTest extends Swift_Transport_StreamBuffer_AbstractStreamBufferAcceptanceTest
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
$streams = stream_get_transports();
|
||||
if (!in_array('ssl', $streams)) {
|
||||
$this->markTestSkipped(
|
||||
'SSL is not configured for your system. It is not possible to run this test'
|
||||
);
|
||||
}
|
||||
if (!defined('SWIFT_SSL_HOST')) {
|
||||
$this->markTestSkipped(
|
||||
'Cannot run test without an SSL enabled SMTP host to connect to (define '.
|
||||
'SWIFT_SSL_HOST in tests/acceptance.conf.php if you wish to run this test)'
|
||||
);
|
||||
}
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
protected function _initializeBuffer()
|
||||
{
|
||||
$parts = explode(':', SWIFT_SSL_HOST);
|
||||
$host = $parts[0];
|
||||
$port = isset($parts[1]) ? $parts[1] : 25;
|
||||
|
||||
$this->_buffer->initialize(array(
|
||||
'type' => Swift_Transport_IoBuffer::TYPE_SOCKET,
|
||||
'host' => $host,
|
||||
'port' => $port,
|
||||
'protocol' => 'ssl',
|
||||
'blocking' => 1,
|
||||
'timeout' => 15,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__.'/AbstractStreamBufferAcceptanceTest.php';
|
||||
|
||||
class Swift_Transport_StreamBuffer_TlsSocketAcceptanceTest extends Swift_Transport_StreamBuffer_AbstractStreamBufferAcceptanceTest
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
$streams = stream_get_transports();
|
||||
if (!in_array('tls', $streams)) {
|
||||
$this->markTestSkipped(
|
||||
'TLS is not configured for your system. It is not possible to run this test'
|
||||
);
|
||||
}
|
||||
if (!defined('SWIFT_TLS_HOST')) {
|
||||
$this->markTestSkipped(
|
||||
'Cannot run test without a TLS enabled SMTP host to connect to (define '.
|
||||
'SWIFT_TLS_HOST in tests/acceptance.conf.php if you wish to run this test)'
|
||||
);
|
||||
}
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
protected function _initializeBuffer()
|
||||
{
|
||||
$parts = explode(':', SWIFT_TLS_HOST);
|
||||
$host = $parts[0];
|
||||
$port = isset($parts[1]) ? $parts[1] : 25;
|
||||
|
||||
$this->_buffer->initialize(array(
|
||||
'type' => Swift_Transport_IoBuffer::TYPE_SOCKET,
|
||||
'host' => $host,
|
||||
'port' => $port,
|
||||
'protocol' => 'tls',
|
||||
'blocking' => 1,
|
||||
'timeout' => 15,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload.php';
|
||||
|
||||
// Disable garbage collector to prevent segfaults
|
||||
gc_disable();
|
||||
|
||||
set_include_path(get_include_path().PATH_SEPARATOR.dirname(__DIR__).'/lib');
|
||||
|
||||
Mockery::getConfiguration()->allowMockingNonExistentMethods(true);
|
||||
|
||||
if (is_file(__DIR__.'/acceptance.conf.php')) {
|
||||
require_once __DIR__.'/acceptance.conf.php';
|
||||
}
|
||||
if (is_file(__DIR__.'/smoke.conf.php')) {
|
||||
require_once __DIR__.'/smoke.conf.php';
|
||||
}
|
||||
require_once __DIR__.'/StreamCollector.php';
|
||||
require_once __DIR__.'/IdenticalBinaryConstraint.php';
|
||||
require_once __DIR__.'/SwiftMailerTestCase.php';
|
||||
require_once __DIR__.'/SwiftMailerSmokeTestCase.php';
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug111Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testUnstructuredHeaderSlashesShouldNotBeEscaped()
|
||||
{
|
||||
$complicated_header = array(
|
||||
'to' => array(
|
||||
'email1@example.com',
|
||||
'email2@example.com',
|
||||
'email3@example.com',
|
||||
'email4@example.com',
|
||||
'email5@example.com',
|
||||
),
|
||||
'sub' => array(
|
||||
'-name-' => array(
|
||||
'email1',
|
||||
'"email2"',
|
||||
'email3\\',
|
||||
'email4',
|
||||
'email5',
|
||||
),
|
||||
'-url-' => array(
|
||||
'http://google.com',
|
||||
'http://yahoo.com',
|
||||
'http://hotmail.com',
|
||||
'http://aol.com',
|
||||
'http://facebook.com',
|
||||
),
|
||||
),
|
||||
);
|
||||
$json = json_encode($complicated_header);
|
||||
|
||||
$message = new Swift_Message();
|
||||
$headers = $message->getHeaders();
|
||||
$headers->addTextHeader('X-SMTPAPI', $json);
|
||||
$header = $headers->get('X-SMTPAPI');
|
||||
|
||||
$this->assertEquals('Swift_Mime_Headers_UnstructuredHeader', get_class($header));
|
||||
$this->assertEquals($json, $header->getFieldBody());
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug118Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_message;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_message = new Swift_Message();
|
||||
}
|
||||
|
||||
public function testCallingGenerateIdChangesTheMessageId()
|
||||
{
|
||||
$currentId = $this->_message->getId();
|
||||
$this->_message->generateId();
|
||||
$newId = $this->_message->getId();
|
||||
|
||||
$this->assertNotEquals($currentId, $newId);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug206Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_factory;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
|
||||
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
|
||||
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
|
||||
);
|
||||
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(
|
||||
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
|
||||
);
|
||||
$grammar = new Swift_Mime_Grammar();
|
||||
$this->_factory = new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $grammar);
|
||||
}
|
||||
|
||||
public function testMailboxHeaderEncoding()
|
||||
{
|
||||
$this->_testHeaderIsFullyEncoded('email@example.org', 'Family Name, Name', ' "Family Name, Name" <email@example.org>');
|
||||
$this->_testHeaderIsFullyEncoded('email@example.org', 'Family Namé, Name', ' Family =?utf-8?Q?Nam=C3=A9=2C?= Name');
|
||||
$this->_testHeaderIsFullyEncoded('email@example.org', 'Family Namé , Name', ' Family =?utf-8?Q?Nam=C3=A9_=2C?= Name');
|
||||
$this->_testHeaderIsFullyEncoded('email@example.org', 'Family Namé ;Name', ' Family =?utf-8?Q?Nam=C3=A9_=3BName?= ');
|
||||
}
|
||||
|
||||
private function _testHeaderIsFullyEncoded($email, $name, $expected)
|
||||
{
|
||||
$mailboxHeader = $this->_factory->createMailboxHeader('To', array(
|
||||
$email => $name,
|
||||
));
|
||||
|
||||
$headerBody = substr($mailboxHeader->toString(), 3, strlen($expected));
|
||||
|
||||
$this->assertEquals($expected, $headerBody);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug274Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testEmptyFileNameAsAttachment()
|
||||
{
|
||||
$message = new Swift_Message();
|
||||
$this->setExpectedException('Swift_IoException', 'The path cannot be empty');
|
||||
$message->attach(Swift_Attachment::fromPath(''));
|
||||
}
|
||||
|
||||
public function testNonEmptyFileNameAsAttachment()
|
||||
{
|
||||
$message = new Swift_Message();
|
||||
try {
|
||||
$message->attach(Swift_Attachment::fromPath(__FILE__));
|
||||
} catch (Exception $e) {
|
||||
$this->fail('Path should not be empty');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug34Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
Swift_Preferences::getInstance()->setCharset('utf-8');
|
||||
}
|
||||
|
||||
public function testEmbeddedFilesWithMultipartDataCreateMultipartRelatedContentAsAnAlternative()
|
||||
{
|
||||
$message = Swift_Message::newInstance();
|
||||
$message->setCharset('utf-8');
|
||||
$message->setSubject('test subject');
|
||||
$message->addPart('plain part', 'text/plain');
|
||||
|
||||
$image = Swift_Image::newInstance('<image data>', 'image.gif', 'image/gif');
|
||||
$cid = $message->embed($image);
|
||||
|
||||
$message->setBody('<img src="'.$cid.'" />', 'text/html');
|
||||
|
||||
$message->setTo(array('user@domain.tld' => 'User'));
|
||||
|
||||
$message->setFrom(array('other@domain.tld' => 'Other'));
|
||||
$message->setSender(array('other@domain.tld' => 'Other'));
|
||||
|
||||
$id = $message->getId();
|
||||
$date = preg_quote(date('r', $message->getDate()), '~');
|
||||
$boundary = $message->getBoundary();
|
||||
$cidVal = $image->getId();
|
||||
|
||||
$this->assertRegExp(
|
||||
'~^'.
|
||||
'Sender: Other <other@domain.tld>'."\r\n".
|
||||
'Message-ID: <'.$id.'>'."\r\n".
|
||||
'Date: '.$date."\r\n".
|
||||
'Subject: test subject'."\r\n".
|
||||
'From: Other <other@domain.tld>'."\r\n".
|
||||
'To: User <user@domain.tld>'."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: multipart/alternative;'."\r\n".
|
||||
' boundary="'.$boundary.'"'."\r\n".
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: text/plain; charset=utf-8'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'plain part'.
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: multipart/related;'."\r\n".
|
||||
' boundary="(.*?)"'."\r\n".
|
||||
"\r\n\r\n".
|
||||
'--\\1'."\r\n".
|
||||
'Content-Type: text/html; charset=utf-8'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'<img.*?/>'.
|
||||
"\r\n\r\n".
|
||||
'--\\1'."\r\n".
|
||||
'Content-Type: image/gif; name=image.gif'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-ID: <'.$cidVal.'>'."\r\n".
|
||||
'Content-Disposition: inline; filename=image.gif'."\r\n".
|
||||
"\r\n".
|
||||
preg_quote(base64_encode('<image data>'), '~').
|
||||
"\r\n\r\n".
|
||||
'--\\1--'."\r\n".
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary.'--'."\r\n".
|
||||
'$~D',
|
||||
$message->toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug35Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
Swift_Preferences::getInstance()->setCharset('utf-8');
|
||||
}
|
||||
|
||||
public function testHTMLPartAppearsLastEvenWhenAttachmentsAdded()
|
||||
{
|
||||
$message = Swift_Message::newInstance();
|
||||
$message->setCharset('utf-8');
|
||||
$message->setSubject('test subject');
|
||||
$message->addPart('plain part', 'text/plain');
|
||||
|
||||
$attachment = Swift_Attachment::newInstance('<data>', 'image.gif', 'image/gif');
|
||||
$message->attach($attachment);
|
||||
|
||||
$message->setBody('HTML part', 'text/html');
|
||||
|
||||
$message->setTo(array('user@domain.tld' => 'User'));
|
||||
|
||||
$message->setFrom(array('other@domain.tld' => 'Other'));
|
||||
$message->setSender(array('other@domain.tld' => 'Other'));
|
||||
|
||||
$id = $message->getId();
|
||||
$date = preg_quote(date('r', $message->getDate()), '~');
|
||||
$boundary = $message->getBoundary();
|
||||
|
||||
$this->assertRegExp(
|
||||
'~^'.
|
||||
'Sender: Other <other@domain.tld>'."\r\n".
|
||||
'Message-ID: <'.$id.'>'."\r\n".
|
||||
'Date: '.$date."\r\n".
|
||||
'Subject: test subject'."\r\n".
|
||||
'From: Other <other@domain.tld>'."\r\n".
|
||||
'To: User <user@domain.tld>'."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: multipart/mixed;'."\r\n".
|
||||
' boundary="'.$boundary.'"'."\r\n".
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: multipart/alternative;'."\r\n".
|
||||
' boundary="(.*?)"'."\r\n".
|
||||
"\r\n\r\n".
|
||||
'--\\1'."\r\n".
|
||||
'Content-Type: text/plain; charset=utf-8'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'plain part'.
|
||||
"\r\n\r\n".
|
||||
'--\\1'."\r\n".
|
||||
'Content-Type: text/html; charset=utf-8'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'HTML part'.
|
||||
"\r\n\r\n".
|
||||
'--\\1--'."\r\n".
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: image/gif; name=image.gif'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-Disposition: attachment; filename=image.gif'."\r\n".
|
||||
"\r\n".
|
||||
preg_quote(base64_encode('<data>'), '~').
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary.'--'."\r\n".
|
||||
'$~D',
|
||||
$message->toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug38Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_attFile;
|
||||
private $_attFileName;
|
||||
private $_attFileType;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_attFileName = 'data.txt';
|
||||
$this->_attFileType = 'text/plain';
|
||||
$this->_attFile = __DIR__.'/../../_samples/files/data.txt';
|
||||
Swift_Preferences::getInstance()->setCharset('utf-8');
|
||||
}
|
||||
|
||||
public function testWritingMessageToByteStreamProducesCorrectStructure()
|
||||
{
|
||||
$message = new Swift_Message();
|
||||
$message->setSubject('test subject');
|
||||
$message->setTo('user@domain.tld');
|
||||
$message->setCc('other@domain.tld');
|
||||
$message->setFrom('user@domain.tld');
|
||||
|
||||
$image = new Swift_Image('<data>', 'image.gif', 'image/gif');
|
||||
|
||||
$cid = $message->embed($image);
|
||||
$message->setBody('HTML part', 'text/html');
|
||||
|
||||
$id = $message->getId();
|
||||
$date = preg_quote(date('r', $message->getDate()), '~');
|
||||
$boundary = $message->getBoundary();
|
||||
$imgId = $image->getId();
|
||||
|
||||
$stream = new Swift_ByteStream_ArrayByteStream();
|
||||
|
||||
$message->toByteStream($stream);
|
||||
|
||||
$this->assertPatternInStream(
|
||||
'~^'.
|
||||
'Message-ID: <'.$id.'>'."\r\n".
|
||||
'Date: '.$date."\r\n".
|
||||
'Subject: test subject'."\r\n".
|
||||
'From: user@domain.tld'."\r\n".
|
||||
'To: user@domain.tld'."\r\n".
|
||||
'Cc: other@domain.tld'."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: multipart/related;'."\r\n".
|
||||
' boundary="'.$boundary.'"'."\r\n".
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: text/html; charset=utf-8'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'HTML part'.
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: image/gif; name=image.gif'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-ID: <'.preg_quote($imgId, '~').'>'."\r\n".
|
||||
'Content-Disposition: inline; filename=image.gif'."\r\n".
|
||||
"\r\n".
|
||||
preg_quote(base64_encode('<data>'), '~').
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary.'--'."\r\n".
|
||||
'$~D',
|
||||
$stream
|
||||
);
|
||||
}
|
||||
|
||||
public function testWritingMessageToByteStreamTwiceProducesCorrectStructure()
|
||||
{
|
||||
$message = new Swift_Message();
|
||||
$message->setSubject('test subject');
|
||||
$message->setTo('user@domain.tld');
|
||||
$message->setCc('other@domain.tld');
|
||||
$message->setFrom('user@domain.tld');
|
||||
|
||||
$image = new Swift_Image('<data>', 'image.gif', 'image/gif');
|
||||
|
||||
$cid = $message->embed($image);
|
||||
$message->setBody('HTML part', 'text/html');
|
||||
|
||||
$id = $message->getId();
|
||||
$date = preg_quote(date('r', $message->getDate()), '~');
|
||||
$boundary = $message->getBoundary();
|
||||
$imgId = $image->getId();
|
||||
|
||||
$pattern = '~^'.
|
||||
'Message-ID: <'.$id.'>'."\r\n".
|
||||
'Date: '.$date."\r\n".
|
||||
'Subject: test subject'."\r\n".
|
||||
'From: user@domain.tld'."\r\n".
|
||||
'To: user@domain.tld'."\r\n".
|
||||
'Cc: other@domain.tld'."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: multipart/related;'."\r\n".
|
||||
' boundary="'.$boundary.'"'."\r\n".
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: text/html; charset=utf-8'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'HTML part'.
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: image/gif; name=image.gif'."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-ID: <'.preg_quote($imgId, '~').'>'."\r\n".
|
||||
'Content-Disposition: inline; filename=image.gif'."\r\n".
|
||||
"\r\n".
|
||||
preg_quote(base64_encode('<data>'), '~').
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary.'--'."\r\n".
|
||||
'$~D'
|
||||
;
|
||||
|
||||
$streamA = new Swift_ByteStream_ArrayByteStream();
|
||||
$streamB = new Swift_ByteStream_ArrayByteStream();
|
||||
|
||||
$message->toByteStream($streamA);
|
||||
$message->toByteStream($streamB);
|
||||
|
||||
$this->assertPatternInStream($pattern, $streamA);
|
||||
$this->assertPatternInStream($pattern, $streamB);
|
||||
}
|
||||
|
||||
public function testWritingMessageToByteStreamTwiceUsingAFileAttachment()
|
||||
{
|
||||
$message = new Swift_Message();
|
||||
$message->setSubject('test subject');
|
||||
$message->setTo('user@domain.tld');
|
||||
$message->setCc('other@domain.tld');
|
||||
$message->setFrom('user@domain.tld');
|
||||
|
||||
$attachment = Swift_Attachment::fromPath($this->_attFile);
|
||||
|
||||
$message->attach($attachment);
|
||||
|
||||
$message->setBody('HTML part', 'text/html');
|
||||
|
||||
$id = $message->getId();
|
||||
$date = preg_quote(date('r', $message->getDate()), '~');
|
||||
$boundary = $message->getBoundary();
|
||||
|
||||
$streamA = new Swift_ByteStream_ArrayByteStream();
|
||||
$streamB = new Swift_ByteStream_ArrayByteStream();
|
||||
|
||||
$pattern = '~^'.
|
||||
'Message-ID: <'.$id.'>'."\r\n".
|
||||
'Date: '.$date."\r\n".
|
||||
'Subject: test subject'."\r\n".
|
||||
'From: user@domain.tld'."\r\n".
|
||||
'To: user@domain.tld'."\r\n".
|
||||
'Cc: other@domain.tld'."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: multipart/mixed;'."\r\n".
|
||||
' boundary="'.$boundary.'"'."\r\n".
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: text/html; charset=utf-8'."\r\n".
|
||||
'Content-Transfer-Encoding: quoted-printable'."\r\n".
|
||||
"\r\n".
|
||||
'HTML part'.
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary."\r\n".
|
||||
'Content-Type: '.$this->_attFileType.'; name='.$this->_attFileName."\r\n".
|
||||
'Content-Transfer-Encoding: base64'."\r\n".
|
||||
'Content-Disposition: attachment; filename='.$this->_attFileName."\r\n".
|
||||
"\r\n".
|
||||
preg_quote(base64_encode(file_get_contents($this->_attFile)), '~').
|
||||
"\r\n\r\n".
|
||||
'--'.$boundary.'--'."\r\n".
|
||||
'$~D'
|
||||
;
|
||||
|
||||
$message->toByteStream($streamA);
|
||||
$message->toByteStream($streamB);
|
||||
|
||||
$this->assertPatternInStream($pattern, $streamA);
|
||||
$this->assertPatternInStream($pattern, $streamB);
|
||||
}
|
||||
|
||||
public function assertPatternInStream($pattern, $stream, $message = '%s')
|
||||
{
|
||||
$string = '';
|
||||
while (false !== $bytes = $stream->read(8192)) {
|
||||
$string .= $bytes;
|
||||
}
|
||||
$this->assertRegExp($pattern, $string, $message);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Mockery as m;
|
||||
|
||||
class Swift_Bug518Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testIfEmailChangesAfterQueued()
|
||||
{
|
||||
$failedRecipients = 'value';
|
||||
$message = new Swift_Message();
|
||||
$message->setTo('foo@bar.com');
|
||||
|
||||
$that = $this;
|
||||
$messageValidation = function ($m) use ($that) {
|
||||
//the getTo should return the same value as we put in
|
||||
$that->assertEquals('foo@bar.com', key($m->getTo()), 'The message has changed after it was put to the memory queue');
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
$transport = m::mock('Swift_Transport');
|
||||
$transport->shouldReceive('isStarted')->andReturn(true);
|
||||
$transport->shouldReceive('send')
|
||||
->with(m::on($messageValidation), $failedRecipients)
|
||||
->andReturn(1);
|
||||
|
||||
$memorySpool = new Swift_MemorySpool();
|
||||
$memorySpool->queueMessage($message);
|
||||
|
||||
/*
|
||||
* The message is queued in memory.
|
||||
* Lets change the message
|
||||
*/
|
||||
$message->setTo('other@value.com');
|
||||
|
||||
$memorySpool->flushQueue($transport, $failedRecipients);
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug51Test extends \SwiftMailerTestCase
|
||||
{
|
||||
private $_attachmentFile;
|
||||
private $_outputFile;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_attachmentFile = sys_get_temp_dir().'/attach.rand.bin';
|
||||
file_put_contents($this->_attachmentFile, '');
|
||||
|
||||
$this->_outputFile = sys_get_temp_dir().'/attach.out.bin';
|
||||
file_put_contents($this->_outputFile, '');
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
unlink($this->_attachmentFile);
|
||||
unlink($this->_outputFile);
|
||||
}
|
||||
|
||||
public function testAttachmentsDoNotGetTruncatedUsingToByteStream()
|
||||
{
|
||||
//Run 100 times with 10KB attachments
|
||||
for ($i = 0; $i < 10; ++$i) {
|
||||
$message = $this->_createMessageWithRandomAttachment(
|
||||
10000, $this->_attachmentFile
|
||||
);
|
||||
|
||||
file_put_contents($this->_outputFile, '');
|
||||
$message->toByteStream(
|
||||
new Swift_ByteStream_FileByteStream($this->_outputFile, true)
|
||||
);
|
||||
|
||||
$emailSource = file_get_contents($this->_outputFile);
|
||||
|
||||
$this->assertAttachmentFromSourceMatches(
|
||||
file_get_contents($this->_attachmentFile),
|
||||
$emailSource
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAttachmentsDoNotGetTruncatedUsingToString()
|
||||
{
|
||||
//Run 100 times with 10KB attachments
|
||||
for ($i = 0; $i < 10; ++$i) {
|
||||
$message = $this->_createMessageWithRandomAttachment(
|
||||
10000, $this->_attachmentFile
|
||||
);
|
||||
|
||||
$emailSource = $message->toString();
|
||||
|
||||
$this->assertAttachmentFromSourceMatches(
|
||||
file_get_contents($this->_attachmentFile),
|
||||
$emailSource
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function assertAttachmentFromSourceMatches($attachmentData, $source)
|
||||
{
|
||||
$encHeader = 'Content-Transfer-Encoding: base64';
|
||||
$base64declaration = strpos($source, $encHeader);
|
||||
|
||||
$attachmentDataStart = strpos($source, "\r\n\r\n", $base64declaration);
|
||||
$attachmentDataEnd = strpos($source, "\r\n--", $attachmentDataStart);
|
||||
|
||||
if (false === $attachmentDataEnd) {
|
||||
$attachmentBase64 = trim(substr($source, $attachmentDataStart));
|
||||
} else {
|
||||
$attachmentBase64 = trim(substr(
|
||||
$source, $attachmentDataStart,
|
||||
$attachmentDataEnd - $attachmentDataStart
|
||||
));
|
||||
}
|
||||
|
||||
$this->assertIdenticalBinary($attachmentData, base64_decode($attachmentBase64));
|
||||
}
|
||||
|
||||
private function _fillFileWithRandomBytes($byteCount, $file)
|
||||
{
|
||||
// I was going to use dd with if=/dev/random but this way seems more
|
||||
// cross platform even if a hella expensive!!
|
||||
|
||||
file_put_contents($file, '');
|
||||
$fp = fopen($file, 'wb');
|
||||
for ($i = 0; $i < $byteCount; ++$i) {
|
||||
$byteVal = rand(0, 255);
|
||||
fwrite($fp, pack('i', $byteVal));
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
private function _createMessageWithRandomAttachment($size, $attachmentPath)
|
||||
{
|
||||
$this->_fillFileWithRandomBytes($size, $attachmentPath);
|
||||
|
||||
$message = Swift_Message::newInstance()
|
||||
->setSubject('test')
|
||||
->setBody('test')
|
||||
->setFrom('a@b.c')
|
||||
->setTo('d@e.f')
|
||||
->attach(Swift_Attachment::fromPath($attachmentPath))
|
||||
;
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Mockery as m;
|
||||
|
||||
class Swift_Bug534Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testEmbeddedImagesAreEmbedded()
|
||||
{
|
||||
$message = Swift_Message::newInstance()
|
||||
->setFrom('from@example.com')
|
||||
->setTo('to@example.com')
|
||||
->setSubject('test')
|
||||
;
|
||||
$cid = $message->embed(Swift_Image::fromPath(__DIR__.'/../../_samples/files/swiftmailer.png'));
|
||||
$message->setBody('<img src="'.$cid.'" />', 'text/html');
|
||||
|
||||
$that = $this;
|
||||
$messageValidation = function (Swift_Mime_Message $message) use ($that) {
|
||||
preg_match('/cid:(.*)"/', $message->toString(), $matches);
|
||||
$cid = $matches[1];
|
||||
preg_match('/Content-ID: <(.*)>/', $message->toString(), $matches);
|
||||
$contentId = $matches[1];
|
||||
$that->assertEquals($cid, $contentId, 'cid in body and mime part Content-ID differ');
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
$failedRecipients = array();
|
||||
|
||||
$transport = m::mock('Swift_Transport');
|
||||
$transport->shouldReceive('isStarted')->andReturn(true);
|
||||
$transport->shouldReceive('send')->with(m::on($messageValidation), $failedRecipients)->andReturn(1);
|
||||
|
||||
$memorySpool = new Swift_MemorySpool();
|
||||
$memorySpool->queueMessage($message);
|
||||
$memorySpool->flushQueue($transport, $failedRecipients);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug650Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider encodingDataProvider
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $expectedEncodedName
|
||||
*/
|
||||
public function testMailboxHeaderEncoding($name, $expectedEncodedName)
|
||||
{
|
||||
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
|
||||
$charStream = new Swift_CharacterStream_NgCharacterStream($factory, 'utf-8');
|
||||
$encoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder($charStream);
|
||||
$header = new Swift_Mime_Headers_MailboxHeader('To', $encoder, new Swift_Mime_Grammar());
|
||||
$header->setCharset('utf-8');
|
||||
|
||||
$header->setNameAddresses(array(
|
||||
'test@example.com' => $name,
|
||||
));
|
||||
|
||||
$this->assertSame('To: '.$expectedEncodedName." <test@example.com>\r\n", $header->toString());
|
||||
}
|
||||
|
||||
public function encodingDataProvider()
|
||||
{
|
||||
return array(
|
||||
array('this is " a test ö', 'this is =?utf-8?Q?=22?= a test =?utf-8?Q?=C3=B6?='),
|
||||
array(': this is a test ö', '=?utf-8?Q?=3A?= this is a test =?utf-8?Q?=C3=B6?='),
|
||||
array('( test ö', '=?utf-8?Q?=28?= test =?utf-8?Q?=C3=B6?='),
|
||||
array('[ test ö', '=?utf-8?Q?=5B?= test =?utf-8?Q?=C3=B6?='),
|
||||
array('@ test ö)', '=?utf-8?Q?=40?= test =?utf-8?Q?=C3=B6=29?='),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug71Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_message;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_message = new Swift_Message('test');
|
||||
}
|
||||
|
||||
public function testCallingToStringAfterSettingNewBodyReflectsChanges()
|
||||
{
|
||||
$this->_message->setBody('BODY1');
|
||||
$this->assertRegExp('/BODY1/', $this->_message->toString());
|
||||
|
||||
$this->_message->setBody('BODY2');
|
||||
$this->assertRegExp('/BODY2/', $this->_message->toString());
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Swift_Bug76Test extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_inputFile;
|
||||
private $_outputFile;
|
||||
private $_encoder;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_inputFile = sys_get_temp_dir().'/in.bin';
|
||||
file_put_contents($this->_inputFile, '');
|
||||
|
||||
$this->_outputFile = sys_get_temp_dir().'/out.bin';
|
||||
file_put_contents($this->_outputFile, '');
|
||||
|
||||
$this->_encoder = $this->_createEncoder();
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
unlink($this->_inputFile);
|
||||
unlink($this->_outputFile);
|
||||
}
|
||||
|
||||
public function testBase64EncodedLineLengthNeverExceeds76CharactersEvenIfArgsDo()
|
||||
{
|
||||
$this->_fillFileWithRandomBytes(1000, $this->_inputFile);
|
||||
|
||||
$os = $this->_createStream($this->_inputFile);
|
||||
$is = $this->_createStream($this->_outputFile);
|
||||
|
||||
$this->_encoder->encodeByteStream($os, $is, 0, 80); //Exceeds 76
|
||||
|
||||
$this->assertMaxLineLength(76, $this->_outputFile,
|
||||
'%s: Line length should not exceed 76 characters'
|
||||
);
|
||||
}
|
||||
|
||||
public function assertMaxLineLength($length, $filePath, $message = '%s')
|
||||
{
|
||||
$lines = file($filePath);
|
||||
foreach ($lines as $line) {
|
||||
$this->assertTrue((strlen(trim($line)) <= 76), $message);
|
||||
}
|
||||
}
|
||||
|
||||
private function _fillFileWithRandomBytes($byteCount, $file)
|
||||
{
|
||||
// I was going to use dd with if=/dev/random but this way seems more
|
||||
// cross platform even if a hella expensive!!
|
||||
|
||||
file_put_contents($file, '');
|
||||
$fp = fopen($file, 'wb');
|
||||
for ($i = 0; $i < $byteCount; ++$i) {
|
||||
$byteVal = rand(0, 255);
|
||||
fwrite($fp, pack('i', $byteVal));
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
private function _createEncoder()
|
||||
{
|
||||
return new Swift_Mime_ContentEncoder_Base64ContentEncoder();
|
||||
}
|
||||
|
||||
private function _createStream($file)
|
||||
{
|
||||
return new Swift_ByteStream_FileByteStream($file, true);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
class Swift_FileByteStreamConsecutiveReadCalls extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
* @expectedException \Swift_IoException
|
||||
*/
|
||||
public function shouldThrowExceptionOnConsecutiveRead()
|
||||
{
|
||||
$fbs = new \Swift_ByteStream_FileByteStream('does not exist');
|
||||
try {
|
||||
$fbs->read(100);
|
||||
} catch (\Swift_IoException $exc) {
|
||||
$fbs->read(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user