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
49 changes: 49 additions & 0 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
on:
- push

name: Run PHPStan checks

jobs:
mutation:
name: PHPStan ${{ matrix.php }}-${{ matrix.os }}

runs-on: ${{ matrix.os }}

strategy:
matrix:
os:
- ubuntu-latest

php:
- "8.2"
- "8.3"
- "8.4"

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

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: "${{ matrix.php }}"
coverage: pcov
ini-values: assert.exception=1, zend.assertions=1, error_reporting=-1, log_errors_max_len=0, display_errors=On
tools: composer:v2, cs2pr

- name: Determine composer cache directory
run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV

- name: Cache dependencies installed with composer
uses: actions/cache@v4
with:
path: ${{ env.COMPOSER_CACHE_DIR }}
key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }}
restore-keys: |
php${{ matrix.php }}-composer-

- name: Install dependencies with composer
run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi

- name: Run static analysis with PHPStan
run: vendor/bin/phpstan analyse
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
# dot-mail

> [!IMPORTANT]
Dotkernel's mail service.

> dot-mail is a wrapper on top of [symfony mailer](https://github.com/symfony/mailer)

## dot-mail badges
## Documentation

Documentation is available at: https://docs.dotkernel.org/dot-mail/.

## Badges

![OSS Lifecycle](https://img.shields.io/osslifecycle/dotkernel/dot-mail)
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-mail/5.2.1)
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-mail/5.3.0)

[![GitHub issues](https://img.shields.io/github/issues/dotkernel/dot-mail)](https://github.com/dotkernel/dot-mail/issues)
[![GitHub forks](https://img.shields.io/github/forks/dotkernel/dot-mail)](https://github.com/dotkernel/dot-mail/network)
[![GitHub stars](https://img.shields.io/github/stars/dotkernel/dot-mail)](https://github.com/dotkernel/dot-mail/stargazers)
[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-mail)](https://github.com/dotkernel/dot-mail/blob/5.0/LICENSE.md)
[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-mail)](https://github.com/dotkernel/dot-mail/blob/5.2/LICENSE.md)

[![Build Static](https://github.com/dotkernel/dot-mail/actions/workflows/continuous-integration.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/dot-mail/actions/workflows/continuous-integration.yml)
[![codecov](https://codecov.io/gh/dotkernel/dot-mail/branch/5.0/graph/badge.svg?token=G51NEHYKD3)](https://codecov.io/gh/dotkernel/dot-mail)
[![Build Static](https://github.com/dotkernel/dot-mail/actions/workflows/continuous-integration.yml/badge.svg?branch=5.2)](https://github.com/dotkernel/dot-mail/actions/workflows/continuous-integration.yml)
[![codecov](https://codecov.io/gh/dotkernel/dot-mail/branch/5.2/graph/badge.svg?token=G51NEHYKD3)](https://codecov.io/gh/dotkernel/dot-mail)
[![PHPStan](https://github.com/dotkernel/dot-mail/actions/workflows/static-analysis.yml/badge.svg?branch=5.2)](https://github.com/dotkernel/dot-mail/actions/workflows/static-analysis.yml)

## Installation

Expand Down
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
"require-dev": {
"laminas/laminas-coding-standard": "^3.0",
"mikey179/vfsstream": "^v1.6.11",
"phpunit/phpunit": "^10.5",
"vimeo/psalm": "^6.0"
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^10.2"
},
"autoload": {
"psr-4": {
Expand All @@ -59,7 +60,6 @@
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
"static-analysis": "psalm --shepherd --stats"
"static-analysis": "phpstan analyse --memory-limit 1G"
}
}
16 changes: 16 additions & 0 deletions docs/book/v5/overview.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
# Overview

Dotkernel's mail service.

> dot-mail is a wrapper on top of [symfony mailer](https://github.com/symfony/mailer)

## Badges

![OSS Lifecycle](https://img.shields.io/osslifecycle/dotkernel/dot-mail)
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-mail/5.3.0)

[![GitHub issues](https://img.shields.io/github/issues/dotkernel/dot-mail)](https://github.com/dotkernel/dot-mail/issues)
[![GitHub forks](https://img.shields.io/github/forks/dotkernel/dot-mail)](https://github.com/dotkernel/dot-mail/network)
[![GitHub stars](https://img.shields.io/github/stars/dotkernel/dot-mail)](https://github.com/dotkernel/dot-mail/stargazers)
[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-mail)](https://github.com/dotkernel/dot-mail/blob/5.2/LICENSE.md)

[![Build Static](https://github.com/dotkernel/dot-mail/actions/workflows/continuous-integration.yml/badge.svg?branch=5.2)](https://github.com/dotkernel/dot-mail/actions/workflows/continuous-integration.yml)
[![codecov](https://codecov.io/gh/dotkernel/dot-mail/branch/5.2/graph/badge.svg?token=G51NEHYKD3)](https://codecov.io/gh/dotkernel/dot-mail)
[![PHPStan](https://github.com/dotkernel/dot-mail/actions/workflows/static-analysis.yml/badge.svg?branch=5.2)](https://github.com/dotkernel/dot-mail/actions/workflows/static-analysis.yml)

## Extra features

- the option to log the results of the mailing process it provides the developer with more information and greater control.
8 changes: 8 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
parameters:
level: 5
paths:
- src
- test
treatPhpDocTypesAsCertain: false
12 changes: 0 additions & 12 deletions psalm-baseline.xml

This file was deleted.

17 changes: 0 additions & 17 deletions psalm.xml

This file was deleted.

25 changes: 9 additions & 16 deletions src/Email.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use DateTimeInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Exception\LogicException;
use Symfony\Component\Mime\Header\MailboxListHeader;
use Symfony\Component\Mime\Message;
use Symfony\Component\Mime\Part\AbstractPart;
use Symfony\Component\Mime\Part\Multipart\AlternativePart;
Expand Down Expand Up @@ -46,13 +47,10 @@ class Email extends Message
private ?string $textCharset = null;
private ?string $html = null;

private ?string $htmlCharset = null;
private array $attachments = [];
private ?AbstractPart $cachedBody = null;
private ?string $htmlCharset = null;
private array $attachments = [];
private mixed $cachedBody;

/**
* @return $this
*/
public function subject(string $subject): static
{
return $this->setHeaderBody('Text', 'Subject', $subject);
Expand All @@ -63,9 +61,6 @@ public function getSubject(): ?string
return $this->getHeaders()->getHeaderBody('Subject');
}

/**
* @return $this
*/
public function date(DateTimeInterface $dateTime): static
{
return $this->setHeaderBody('Date', 'Date', $dateTime);
Expand All @@ -76,9 +71,6 @@ public function getDate(): ?DateTimeImmutable
return $this->getHeaders()->getHeaderBody('Date');
}

/**
* @return $this
*/
public function returnPath(Address|string $address): static
{
return $this->setHeaderBody('Path', 'Return-Path', Address::create($address));
Expand Down Expand Up @@ -201,7 +193,7 @@ public function getPriority(): int
{
[$priority] = sscanf($this->getHeaders()->getHeaderBody('X-Priority') ?? '', '%[1-5]');

return (int) $priority ?? 3;
return $priority !== null ? (int) $priority : 3;
}

public function text(string $body, string $charset = 'utf-8'): static
Expand Down Expand Up @@ -315,7 +307,7 @@ private function generateBody(): AbstractPart
return $part ?? new TextPart($this->text, $this->textCharset);
}

private function prepareParts(): ?array
private function prepareParts(): array
{
$names = [];
$htmlPart = null;
Expand Down Expand Up @@ -373,7 +365,8 @@ private function setHeaderBody(string $type, string $name, mixed $body): static

private function addListAddressHeaderBody(string $name, array $addresses): static
{
if (! $header = $this->getHeaders()->get($name)) {
$header = $this->getHeaders()->get($name);
if (! $header instanceof MailboxListHeader) {
return $this->setListAddressHeaderBody($name, $addresses);
}
$header->addAddresses(Address::createArray($addresses));
Expand All @@ -385,7 +378,7 @@ private function setListAddressHeaderBody(string $name, array $addresses): stati
{
$addresses = Address::createArray($addresses);
$headers = $this->getHeaders();
if ($header = $headers->get($name)) {
if (($header = $headers->get($name)) instanceof MailboxListHeader) {
$header->setAddresses($addresses);
} else {
$headers->addMailboxListHeader($name, $addresses);
Expand Down
8 changes: 4 additions & 4 deletions test/Event/MailEventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ public function testMailEventCanBeCreated(): void
{
$defaultMailEvent = new MailEvent($this->mailService);

$this->assertInstanceOf(MailEvent::class, $defaultMailEvent);
$this->assertInstanceOf(MailServiceInterface::class, $defaultMailEvent->getMailService());
$this->assertContainsOnlyInstancesOf(MailEvent::class, [$defaultMailEvent]);
$this->assertContainsOnlyInstancesOf(MailServiceInterface::class, [$defaultMailEvent->getMailService()]);

$customMailEvent = new MailEvent($this->mailService, MailEvent::EVENT_MAIL_SEND_ERROR);
$mailServiceInterface = $this->createMock(MailServiceInterface::class);
$customMailEvent->setMailService($mailServiceInterface);

$this->assertInstanceOf(MailEvent::class, $customMailEvent);
$this->assertContainsOnlyInstancesOf(MailEvent::class, [$customMailEvent]);
$this->assertSame(MailEvent::EVENT_MAIL_SEND_ERROR, $customMailEvent->getName());
$this->assertInstanceOf(MailServiceInterface::class, $customMailEvent->getMailService());
$this->assertContainsOnlyInstancesOf(MailServiceInterface::class, [$customMailEvent->getMailService()]);
}

public function testEventPropagation(): void
Expand Down
4 changes: 2 additions & 2 deletions test/Factory/MailOptionsAbstractFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function testGeneratesMailOptions(): void

$subject = (new MailOptionsAbstractFactory())($container, $defaultName);

$this->assertInstanceOf(MailOptions::class, $subject);
$this->assertContainsOnlyInstancesOf(MailOptions::class, [$subject]);
}

/**
Expand All @@ -73,6 +73,6 @@ public function testIsSpecificConfigArray(): void

$subject = (new MailOptionsAbstractFactory())($container, $defaultName);

$this->assertInstanceOf(MailOptions::class, $subject);
$this->assertContainsOnlyInstancesOf(MailOptions::class, [$subject]);
}
}
8 changes: 4 additions & 4 deletions test/Factory/MailServiceAbstractFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public function testGenerateServiceWithProvidedAdapter(): void
->method('getSmtpOptions')
->willReturn($this->smtpOptions);

$mailService = (new Subject())($this->container, $requestedName);
$mailService = ($this->subject)($this->container, $requestedName);
$this->assertInstanceOf(MailService::class, $mailService);
$this->assertInstanceOf(EsmtpTransport::class, $mailService->getTransport());
}
Expand Down Expand Up @@ -197,7 +197,7 @@ public function testGenerateServiceWithoutProvidedAdapter(): void

$this->expectException(RuntimeException::class);

$mailService = (new Subject())($this->container, $requestedName);
$mailService = ($this->subject)($this->container, $requestedName);

$this->assertInstanceOf(MailService::class, $mailService);
$this->assertInstanceOf(EsmtpTransport::class, $mailService->getTransport());
Expand Down Expand Up @@ -226,7 +226,7 @@ public function testGenerateServiceInvalidAdapter(): void
]);

$this->expectException(InvalidArgumentException::class);
(new Subject())($this->container, $requestedName);
($this->subject)($this->container, $requestedName);
}

/**
Expand Down Expand Up @@ -258,6 +258,6 @@ public function testGenerateServiceThrowException(): void
]);

$this->expectException(InvalidArgumentException::class);
(new Subject())($this->container, $requestedName);
($this->subject)($this->container, $requestedName);
}
}
4 changes: 2 additions & 2 deletions test/Options/MailOptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ public function testGettersAndSetters(): void

$this->assertSame(EsmtpTransport::class, $subject->getTransport());
$this->assertSame($transportMap, $subject->getTransportMap());
$this->assertInstanceOf(MessageOptions::class, $subject->getMessageOptions());
$this->assertInstanceOf(SmtpOptions::class, $subject->getSmtpOptions());
$this->assertContainsOnlyInstancesOf(MessageOptions::class, [$subject->getMessageOptions()]);
$this->assertContainsOnlyInstancesOf(SmtpOptions::class, [$subject->getSmtpOptions()]);
$this->assertSame($eventListeners, $subject->getEventListeners());
}
}
4 changes: 2 additions & 2 deletions test/Options/MessageOptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function testGettersAndSetters(): void
$this->assertSame($cc, $subject->getCc());
$this->assertSame($bcc, $subject->getBcc());
$this->assertSame($messageSubject, $subject->getSubject());
$this->assertInstanceOf(BodyOptions::class, $subject->getBody());
$this->assertInstanceOf(AttachmentsOptions::class, $subject->getAttachments());
$this->assertContainsOnlyInstancesOf(BodyOptions::class, [$subject->getBody()]);
$this->assertContainsOnlyInstancesOf(AttachmentsOptions::class, [$subject->getAttachments()]);
}
}
4 changes: 2 additions & 2 deletions test/Service/MailServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ public function testGettersAndSetters(): void
public function testCreateMailEvent(): void
{
$defaultMailEvent = $this->mailService->createMailEvent();
$this->assertInstanceOf(MailEvent::class, $defaultMailEvent);
$this->assertContainsOnlyInstancesOf(MailEvent::class, [$defaultMailEvent]);
$this->assertSame(MailEvent::EVENT_MAIL_PRE_SEND, $defaultMailEvent->getName());

$result = new MailResult();
$mailEvent = $this->mailService->createMailEvent('testName', $result);
$this->assertInstanceOf(MailEvent::class, $mailEvent);
$this->assertContainsOnlyInstancesOf(MailEvent::class, [$mailEvent]);
$this->assertSame('testName', $mailEvent->getName());
$this->assertSame(MailResult::DEFAULT_MESSAGE, $mailEvent->getResult()->getMessage());
}
Expand Down