diff --git a/.github/workflows/php-tests.yml b/.github/workflows/php-tests.yml
new file mode 100644
index 0000000..0a3df8a
--- /dev/null
+++ b/.github/workflows/php-tests.yml
@@ -0,0 +1,30 @@
+name: PHP Tests
+
+on:
+ push:
+ pull_request:
+
+jobs:
+ test:
+ name: PHP ${{ matrix.php-version }}
+ runs-on: ubuntu-latest
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
+
+ strategy:
+ matrix:
+ php-version: [ '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4' ]
+ max-parallel: 1
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-version }}
+
+ - name: Install Dependencies
+ run: composer install
+
+ - name: Run Tests
+ run: ./vendor/bin/phpunit --configuration phpunit.xml.dist --verbose
diff --git a/.gitignore b/.gitignore
index 96e828d..07cc02f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ composer.lock
.idea/
docs/
phpunit.xml
+.phpunit.result.cache
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index b174b06..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-language: php
-sudo: false
-php:
- - "7.4"
- - "7.3"
- - "7.2"
- - "7.1"
- - "7.0"
- - "5.6"
-install: composer update
-script: ./vendor/bin/phpunit --verbose
diff --git a/composer.json b/composer.json
index e3620d2..e9cc2e2 100644
--- a/composer.json
+++ b/composer.json
@@ -18,11 +18,11 @@
}
],
"require": {
- "php": ">=5.3.2",
+ "php": ">=5.4",
"psr/log": "~1.0"
},
"require-dev": {
- "phpunit/phpunit": "~5.0",
+ "phpunit/phpunit": "~8.5",
"monolog/monolog": "~1.13"
},
"autoload": {
@@ -31,8 +31,8 @@
}
},
"autoload-dev": {
- "classmap": [
- "tests/TestCase.php"
- ]
+ "psr-4": {
+ "Tx\\Mailer\\Tests\\": "tests/"
+ }
}
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 3732559..81b1c2f 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,7 +1,7 @@
-
- vendor
-
+
+
+ vendor
+
+
-
+
diff --git a/src/Mailer/SMTP.php b/src/Mailer/SMTP.php
index 9ed80ef..50bc3c1 100644
--- a/src/Mailer/SMTP.php
+++ b/src/Mailer/SMTP.php
@@ -108,7 +108,8 @@ public function __construct(LoggerInterface $logger=null)
* set server and port
* @param string $host server
* @param int $port port
- * @param string $secure ssl tls tlsv1.0 tlsv1.1 tlsv1.2
+ * @param string $secure ssl tls
+ * @param bool $allowInsecure skip certificate verification?
* @return $this
*/
public function setServer($host, $port, $secure=null, $allowInsecure=null)
@@ -116,7 +117,7 @@ public function setServer($host, $port, $secure=null, $allowInsecure=null)
$this->host = $host;
$this->port = $port;
$this->secure = $secure;
- $this->allowInsecure = $allowInsecure;
+ $this->allowInsecure = (bool) $allowInsecure;
if(!$this->ehlo) $this->ehlo = $host;
$this->logger && $this->logger->debug("Set: the server");
return $this;
@@ -204,7 +205,7 @@ protected function connect()
$this->logger && $this->logger->debug("Connecting to {$this->host} at {$this->port}");
$host = ($this->secure == 'ssl') ? 'ssl://' . $this->host : $this->host;
// Create connection
- $context = null;
+ $context = stream_context_create([]);
if ($this->allowInsecure) {
$context = stream_context_create([
'ssl' => [
@@ -214,7 +215,7 @@ protected function connect()
]
]);
}
- $this->smtp = stream_socket_client(
+ $this->smtp = @stream_socket_client(
$host.':'.$this->port,
$error_code,
$error_message,
@@ -222,10 +223,8 @@ protected function connect()
STREAM_CLIENT_CONNECT,
$context
);
- //set block mode
- // stream_set_blocking($this->smtp, 1);
if (!$this->smtp){
- throw new SMTPException("Could not open SMTP Port.");
+ throw new SMTPException("Could not open SMTP Port to $host:{$this->port}");
}
$code = $this->getCode();
if ($code !== '220'){
@@ -254,24 +253,13 @@ protected function starttls()
throw new CryptoException('Crypto type expected PHP 5.6 or greater');
}
- switch ($this->secure) {
- case 'tlsv1.0':
- $crypto_type = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
- break;
- case 'tlsv1.1':
- $crypto_type = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
- break;
- case 'tlsv1.2':
- $crypto_type = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
- break;
- default:
- $crypto_type = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT |
- STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT |
- STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
- break;
+ if ($this->allowInsecure) {
+ stream_context_set_option($this->smtp, 'ssl', 'verify_peer', false);
+ stream_context_set_option($this->smtp, 'ssl', 'verify_peer_name', false);
+ stream_context_set_option($this->smtp, 'ssl', 'allow_self_signed', true);
}
- if(!\stream_socket_enable_crypto($this->smtp, true, $crypto_type)) {
+ if(!\stream_socket_enable_crypto($this->smtp, true, STREAM_CRYPTO_METHOD_ANY_CLIENT)) {
throw new CryptoException("Start TLS failed to enable crypto");
}
return $this;
diff --git a/tests/MailerTest.php b/tests/MailerTest.php
index 55f54e1..bd5c3e3 100644
--- a/tests/MailerTest.php
+++ b/tests/MailerTest.php
@@ -1,18 +1,13 @@
addTo(self::TO_NAME, self::TO_EMAIL)
->addCc(self::CC_NAME, self::CC_EMAIL)
->addBcc(self::BCC_NAME, self::BCC_EMAIL)
- ->setSubject('Test Mailer '. time())
+ ->setSubject('Test Mailer ' . time())
->setBody('Hi, boy')
->addAttachment('test', __FILE__)
->send();
diff --git a/tests/MessageTest.php b/tests/MessageTest.php
new file mode 100644
index 0000000..55df3c3
--- /dev/null
+++ b/tests/MessageTest.php
@@ -0,0 +1,208 @@
+message = new Message();
+ }
+
+ public function testSetFrom()
+ {
+ $name = 'Sender Name';
+ $email = 'sender@example.com';
+ $expectedHeader = 'From: =?utf-8?B?U2VuZGVyIE5hbWU=?= ';
+
+ $this->message->setFrom($name, $email);
+
+ // Test getters
+ $this->assertEquals($name, $this->message->getFromName());
+ $this->assertEquals($email, $this->message->getFromEmail());
+
+ // Test toString output
+ $messageString = $this->message->toString();
+ $this->assertStringContainsString($expectedHeader, $messageString);
+ }
+
+ public function testSetFakeFrom()
+ {
+ $name = 'Fake Name';
+ $email = 'fake@example.com';
+ $expectedHeader = 'From: =?utf-8?B?RmFrZSBOYW1l?= ';
+
+ $this->message->setFakeFrom($name, $email);
+
+ // Test getters
+ $this->assertEquals($name, $this->message->getFakeFromName());
+ $this->assertEquals($email, $this->message->getFakeFromEmail());
+
+ // Test toString output
+ $messageString = $this->message->toString();
+ $this->assertStringContainsString($expectedHeader, $messageString);
+ }
+
+ public function testAddTo()
+ {
+ $name = 'Recipient';
+ $email = 'recipient@example.com';
+ $expectedHeader = 'To: =?utf-8?B?UmVjaXBpZW50?= ';
+
+ $this->message->addTo($name, $email);
+
+ // Test getter
+ $to = $this->message->getTo();
+ $this->assertArrayHasKey($email, $to);
+ $this->assertEquals($name, $to[$email]);
+
+ // Test toString output
+ $messageString = $this->message->toString();
+ $this->assertStringContainsString($expectedHeader, $messageString);
+ }
+
+ public function testAddCc()
+ {
+ $name = 'CC Recipient';
+ $email = 'cc@example.com';
+ $expectedHeader = 'Cc: =?utf-8?B?Q0MgUmVjaXBpZW50?= ';
+
+ $this->message->addCc($name, $email);
+
+ // Test getter
+ $cc = $this->message->getCc();
+ $this->assertArrayHasKey($email, $cc);
+ $this->assertEquals($name, $cc[$email]);
+
+ // Test toString output
+ $messageString = $this->message->toString();
+ $this->assertStringContainsString($expectedHeader, $messageString);
+ }
+
+ public function testAddBcc()
+ {
+ $name = 'BCC Recipient';
+ $email = 'bcc@example.com';
+ $expectedHeader = 'Bcc: =?utf-8?B?QkNDIFJlY2lwaWVudA==?= ';
+
+ $this->message->addBcc($name, $email);
+
+ // Test getter
+ $bcc = $this->message->getBcc();
+ $this->assertArrayHasKey($email, $bcc);
+ $this->assertEquals($name, $bcc[$email]);
+
+ // Test toString output
+ $messageString = $this->message->toString();
+ $this->assertStringContainsString($expectedHeader, $messageString);
+ }
+
+ public function testSetSubject()
+ {
+ $subject = 'Test Subject with Special Chars: äöü';
+
+ $this->message->setSubject($subject);
+
+ // Test getter
+ $this->assertEquals($subject, $this->message->getSubject());
+
+ // Test toString output
+ $messageString = $this->message->toString();
+ $expectedHeader = 'Subject: =?utf-8?B?VGVzdCBTdWJqZWN0IHdpdGggU3BlY2lhbCBDaGFyczogw6TDtsO8?=';
+ $this->assertStringContainsString($expectedHeader, $messageString);
+ }
+
+ public function testSetBody()
+ {
+ $body = 'Test email body content with special chars: äöü';
+
+ $this->message->setBody($body);
+
+ // Test getter
+ $this->assertEquals($body, $this->message->getBody());
+
+ // Test toString output
+ $messageString = $this->message->toString();
+ $expectedBody = "VGVzdCBlbWFpbCBib2R5IGNvbnRlbnQgd2l0aCBzcGVjaWFsIGNoYXJzOiDDpMO2w7w=\r\n";
+ $this->assertStringContainsString($expectedBody, $messageString);
+ }
+
+ public function testSetReplyTo()
+ {
+ $name = 'Reply Name';
+ $email = 'reply@example.com';
+ $expectedHeader = 'Reply-To: =?utf-8?B?UmVwbHkgTmFtZQ==?= ';
+
+ $this->message->setReplyTo($name, $email);
+
+ // Test toString output
+ $messageString = $this->message->toString();
+ $this->assertStringContainsString($expectedHeader, $messageString);
+ }
+
+ public function testAddAttachment()
+ {
+ $name = 'test.txt';
+ $path = tempnam(sys_get_temp_dir(), 'test_');
+
+
+ // Create a test file
+ file_put_contents($path, 'Test content');
+
+ $this->message->addAttachment($name, $path);
+
+ // Test getter
+ $attachments = $this->message->getAttachment();
+ $this->assertArrayHasKey($name, $attachments);
+ $this->assertEquals($path, $attachments[$name]);
+
+ // Test toString output
+ $messageString = $this->message->toString();
+ $this->assertStringContainsString(
+ 'Content-Type: application/octet-stream; name="' . $name . '"',
+ $messageString
+ );
+ $this->assertStringContainsString(
+ 'Content-Disposition: attachment; filename="' . $name . '"',
+ $messageString
+ );
+
+ // Cleanup
+ unlink($path);
+ }
+
+ public function testCompleteMessage()
+ {
+ $fromName = 'Sender';
+ $fromEmail = 'sender@example.com';
+ $toName = 'Recipient';
+ $toEmail = 'recipient@example.com';
+ $subject = 'Complete Test';
+ $body = 'Complete test body';
+ $expectedHeaderFrom = 'From: =?utf-8?B?U2VuZGVy?= ';
+ $expectedHeaderTo = 'To: =?utf-8?B?UmVjaXBpZW50?= ';
+ $expectedHeaderSubject = 'Subject: =?utf-8?B?Q29tcGxldGUgVGVzdA==?=';
+ $expectedBody = "Q29tcGxldGUgdGVzdCBib2R5\r\n";
+
+ $this->message
+ ->setFrom($fromName, $fromEmail)
+ ->addTo($toName, $toEmail)
+ ->setSubject($subject)
+ ->setBody($body);
+
+ $messageString = $this->message->toString();
+
+ // Verify all parts are present and properly encoded
+
+ $this->assertStringContainsString($expectedHeaderFrom, $messageString);
+ $this->assertStringContainsString($expectedHeaderTo, $messageString);
+ $this->assertStringContainsString($expectedHeaderSubject, $messageString);
+ $this->assertStringContainsString($expectedBody, $messageString);
+ $this->assertStringContainsString('MIME-Version: 1.0', $messageString);
+ $this->assertStringContainsString('Content-Type: multipart/alternative', $messageString);
+ }
+}
diff --git a/tests/OAuthTest.php b/tests/OAuthTest.php
index c9a55d5..02472ae 100644
--- a/tests/OAuthTest.php
+++ b/tests/OAuthTest.php
@@ -1,17 +1,16 @@
markTestSkipped('No oauth token set, test skipped');
}
$mail = new Mailer(new Logger('Mailer.OAuth'));
$status = $mail->setServer(self::OAUTH_SERVER, self::OAUTH_PORT, 'tls')
diff --git a/tests/SMTPTest.php b/tests/SMTPTest.php
index 1e885cd..0b5f6b8 100644
--- a/tests/SMTPTest.php
+++ b/tests/SMTPTest.php
@@ -1,14 +1,10 @@
message = new Message();
$this->message
@@ -69,47 +65,9 @@ public function testTLSSend()
usleep(self::DELAY);
}
- public function testTLSv10Send()
- {
- $this->smtp = new SMTP(new Logger('SMTP.tlsv1.0'));
- $this->smtp
- ->setServer(self::SERVER, self::PORT_TLS, 'tlsv1.0')
- ->setAuth(self::USER, self::PASS);
-
- $status = $this->smtp->send($this->message);
- $this->assertTrue($status);
- usleep(self::DELAY);
- }
-
- public function testTLSv11Send()
- {
- $this->smtp = new SMTP(new Logger('SMTP.tlsv1.1'));
- $this->smtp
- ->setServer(self::SERVER, self::PORT_TLS, 'tlsv1.1')
- ->setAuth(self::USER, self::PASS);
-
- $status = $this->smtp->send($this->message);
- $this->assertTrue($status);
- usleep(self::DELAY);
- }
-
- public function testTLSv12Send()
- {
- $this->smtp = new SMTP(new Logger('SMTP.tlsv1.2'));
- $this->smtp
- ->setServer(self::SERVER, self::PORT_TLS, 'tlsv1.2')
- ->setAuth(self::USER, self::PASS);
-
- $status = $this->smtp->send($this->message);
- $this->assertTrue($status);
- usleep(self::DELAY);
- }
-
- /**
- * @expectedException \Tx\Mailer\Exceptions\SMTPException
- */
public function testConnectSMTPException()
{
+ $this->expectException(\Tx\Mailer\Exceptions\SMTPException::class);
$this->smtp = new SMTP(new Logger('SMTP.FakePort'));
$this->smtp
->setServer('localhost', "99999", null)
diff --git a/tests/TestCase.php b/tests/TestCase.php
index d3b2495..24d37dd 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -1,9 +1,13 @@