Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,44 @@ jobs:
strategy:
matrix:
php-version:
- "8.5"
- "8.4"
- "8.3"
- "8.2"
- "8.1"

steps:
- uses: actions/checkout@v5
- run: composer install
- run: ./vendor/bin/phpunit
- run: composer test

Psalm:
name: Psalm Static Analyzer
runs-on: ubuntu-latest
permissions:
# for github/codeql-action/upload-sarif to upload SARIF results
security-events: write
container:
image: byjg/php:8.4-cli
options: --user root --privileged

steps:
- name: Git checkout
uses: actions/checkout@v4

- name: Composer
run: composer install

- name: Psalm
# Note: Ignoring error code 2, which just signals that some
# flaws were found, not that Psalm itself failed to run.
run: ./vendor/bin/psalm
--show-info=true
--report=psalm-results.sarif || [ $? = 2 ]

- name: Upload Analysis results to GitHub
uses: github/codeql-action/upload-sarif@v4
if: github.ref == 'refs/heads/master'
with:
sarif_file: psalm-results.sarif

Documentation:
if: github.ref == 'refs/heads/master'
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Mail Wrapper

[![Sponsor](https://img.shields.io/badge/Sponsor-%23ea4aaa?logo=githubsponsors&logoColor=white&labelColor=0d1117)](https://github.com/sponsors/byjg)
[![Build Status](https://github.com/byjg/php-mailwrapper/actions/workflows/phpunit.yml/badge.svg?branch=master)](https://github.com/byjg/php-mailwrapper/actions/workflows/phpunit.yml)
[![Opensource ByJG](https://img.shields.io/badge/opensource-byjg-success.svg)](http://opensource.byjg.com)
[![GitHub source](https://img.shields.io/badge/Github-source-informational?logo=github)](https://github.com/byjg/php-mailwrapper/)
Expand Down
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "byjg/mailwrapper",
"description": "A lightweight wrapper for send mail. The interface is tottaly decoupled from the sender. The sender availables are: PHP Mailer, AWS SES Api, Mandril Api.",
"description": "A lightweight wrapper for sending email. The interface is totally decoupled from the sender, providing a single interface for sending mail regardless of the underlying mail service.",
"autoload": {
"psr-4": {
"ByJG\\Mail\\": "src/"
Expand All @@ -14,20 +14,20 @@
"prefer-stable": true,
"minimum-stability": "dev",
"require": {
"php": ">=8.1 <8.5",
"php": ">=8.3 <8.6",
"ext-curl": "*",
"byjg/convert": "^6.0",
"byjg/webrequest": "^6.0",
"aws/aws-sdk-php": "~3.20",
"phpmailer/phpmailer": ">=6.4.1"
},
"require-dev": {
"phpunit/phpunit": "^10|^11",
"vimeo/psalm": "^5.9|^6.12"
"phpunit/phpunit": "^10.5|^11.5",
"vimeo/psalm": "^5.9|^6.13"
},
"scripts": {
"test": "vendor/bin/phpunit",
"psalm": "vendor/bin/psalm"
"psalm": "vendor/bin/psalm --threads=1"
},
"license": "MIT"
}
3 changes: 1 addition & 2 deletions psalm.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<psalm
errorLevel="4"
errorLevel="3"
resolveFromConfigFile="true"
findUnusedBaselineEntry="true"
findUnusedCode="false"
Expand All @@ -11,7 +11,6 @@
>
<projectFiles>
<directory name="src" />
<directory name="tests" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
Expand Down
2 changes: 1 addition & 1 deletion src/Envelope.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace ByJG\Mail;

class Envelope

Check warning on line 5 in src/Envelope.php

View workflow job for this annotation

GitHub Actions / Psalm Static Analyzer

ClassMustBeFinal

src/Envelope.php:5:7: ClassMustBeFinal: Class ByJG\Mail\Envelope is never extended and is not part of the public API, and thus must be made final. (see https://psalm.dev/361)
{
protected string $from = "";
protected array $to = [];
Expand Down Expand Up @@ -163,7 +163,7 @@
"\n"
],
$this->body
);
) ?? $this->body;

return strip_tags($body);
}
Expand Down
18 changes: 9 additions & 9 deletions src/MailerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,26 @@
use ByJG\Util\Uri;
use Psr\Http\Message\UriInterface;

class MailerFactory

Check warning on line 16 in src/MailerFactory.php

View workflow job for this annotation

GitHub Actions / Psalm Static Analyzer

ClassMustBeFinal

src/MailerFactory.php:16:7: ClassMustBeFinal: Class ByJG\Mail\MailerFactory is never extended and is not part of the public API, and thus must be made final. (see https://psalm.dev/361)
{
/** @var array<string, class-string<MailWrapperInterface>> */
private static array $config = [];

/**
* @param string $class
* @param class-string<MailWrapperInterface> $class
*
* @throws InvalidMailHandlerException
*
* @return void
*/
public static function registerMailer(string $class): void
{
if (!in_array(MailWrapperInterface::class, class_implements($class))) {
$implements = class_implements($class);
if ($implements === false || !in_array(MailWrapperInterface::class, $implements)) {
throw new InvalidMailHandlerException('Class not implements ConnectorInterface!');
}

/** @var MailWrapperInterface $class */
/** @var class-string<MailWrapperInterface> $class */
$protocolList = $class::schema();
foreach ($protocolList as $item) {
self::$config[$item] = $class;
Expand All @@ -45,16 +47,14 @@
*/
public static function create(UriInterface|string $connection): MailWrapperInterface
{
$uri = $connection;
if (is_string($connection)) {
$uri = new Uri($connection);
}
$uri = is_string($connection) ? new Uri($connection) : $connection;

if (!isset(self::$config[$uri->getScheme()])) {
$scheme = $uri->getScheme();
if (!isset(self::$config[$scheme])) {
throw new ProtocolNotRegisteredException('Protocol not found/registered!');
}

$class = self::$config[$uri->getScheme()];
$class = self::$config[$scheme];

return new $class($uri);
}
Expand Down
6 changes: 3 additions & 3 deletions src/Wrapper/AmazonSesWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ public function getSesClient(): SesClient
//Send the message (which must be base 64 encoded):
return new SesClient([
'credentials' => new Credentials(
$this->uri->getUsername(),
$this->uri->getPassword()
$this->uri?->getUsername() ?? '',
$this->uri?->getPassword() ?? ''
),
'region' => $this->uri->getHost(),
'region' => $this->uri?->getHost() ?? '',
'version' => '2010-12-01'
]);
}
Expand Down
8 changes: 4 additions & 4 deletions src/Wrapper/MailgunApiWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ public function __construct(Uri $uri, ?ClientInterface $client = null)
*/
public function getRequestObject(): RequestInterface
{
$domainName = $this->uri->getHost();
$domainName = $this->uri?->getHost() ?? '';
$apiUri = $this->getApiUri();

$uri = Uri::getInstance("https://$apiUri/v3/$domainName/messages")
->withUserInfo('api', $this->uri->getUsername());
->withUserInfo('api', $this->uri?->getUsername() ?? '');

return Request::getInstance($uri)->withMethod("POST");
}
Expand Down Expand Up @@ -104,7 +104,7 @@ public function send(Envelope $envelope): SendResult
foreach ($envelope->getAttachments() as $name => $attachment) {
$message[] = new MultiPartItem(
$attachment['disposition'],
file_get_contents($attachment['content']),
file_get_contents($attachment['content']) ?: '',
$name,
$attachment['content-type']
);
Expand All @@ -128,7 +128,7 @@ public function send(Envelope $envelope): SendResult

private function getApiUri()
{
$query = $this->uri->getQueryPart('region');
$query = $this->uri?->getQueryPart('region');
if (isset($this->regions[$query])) {
return $this->regions[$query];
}
Expand Down
16 changes: 7 additions & 9 deletions src/Wrapper/PHPMailerWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ protected function prepareMailer(Envelope $envelope): PHPMailerOverride

$mail->isSMTP(); // telling the class to use SMTP

if ($this->uri->getScheme() != "smtp") {
$mail->SMTPSecure = $this->uri->getScheme(); // ssl ou tls!
if ($this->uri?->getScheme() != "smtp") {
$mail->SMTPSecure = $this->uri?->getScheme() ?? ''; // ssl ou tls!
}

$replyTo = Util::decomposeEmail($envelope->getReplyTo());
Expand Down Expand Up @@ -114,14 +114,12 @@ public function send(Envelope $envelope): SendResult

$mail = $this->prepareMailer($envelope);

$mail->Host = $this->uri->getHost();
$mail->Port = $this->uri->getPort();
$mail->Host = $this->uri?->getHost() ?? '';
$mail->Port = $this->uri?->getPort() ?? 25;

if (!empty($this->uri->getUsername())) {
$mail->SMTPAuth = true;
$mail->Username = $this->uri->getUsername(); // SMTP account username
$mail->Password = $this->uri->getPassword(); // SMTP account password
}
$mail->SMTPAuth = !empty($this->uri?->getUsername());
$mail->Username = $this->uri?->getUsername() ?? ''; // SMTP account username
$mail->Password = $this->uri?->getPassword() ?? ''; // SMTP account password

if (!$mail->send()) {
throw new MailApiException($mail->ErrorInfo);
Expand Down
Loading