Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
abmmhasan committed Sep 7, 2024
1 parent 454eeff commit 8b36cb8
Show file tree
Hide file tree
Showing 17 changed files with 1,048 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
tests export-ignore
docs export-ignore
.github export-ignore
.readthedocs.yaml export-ignore
captainhook.json export-ignore
phpunit.xml export-ignore
pint.json export-ignore
rector.php export-ignore
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @abmmhasan
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
45 changes: 45 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: "Security & Standards"

on:
schedule:
- cron: '0 0 * * 0'
push:
branches: [ '*' ]
pull_request:
branches: [ "main", "master", "develop" ]

jobs:
run:
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
operating-system: [ ubuntu-latest ]
php-versions: [ '8.2', '8.3' ]
dependency-version: [ prefer-lowest, prefer-stable ]

name: PHP ${{ matrix.php-versions }} - ${{ matrix.operating-system }} - ${{ matrix.dependency-version }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
tools: composer:v2
coverage: xdebug

- name: Check PHP Version
run: php -v

- name: Validate Composer
run: composer validate --strict

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

- name: Package Audit
run: composer audit

- name: Test
run: composer tests
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
vendor
example
.idea
example.php
test.php
composer.lock
git-story_media
14 changes: 14 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Security Policy

![Libraries.io dependency status for GitHub repo](https://img.shields.io/librariesio/github/infocyph/otp)

## Supported Versions

| Version | Supported |
|--------------|--------------------|
| 4.x | :white_check_mark: |
| 3.x or Older | :x: |

## Reporting a Vulnerability

Report any vulnerabilities to the [security advisory tracker](https://github.com/infocyph/otp/issues)!
51 changes: 51 additions & 0 deletions captainhook.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"commit-msg": {
"enabled": false,
"actions": []
},
"pre-push": {
"enabled": false,
"actions": []
},
"pre-commit": {
"enabled": true,
"actions": [
{
"action": "composer validate --strict",
"options": []
},
{
"action": "composer audit",
"options": []
},
{
"action": "composer tests",
"options": []
}
]
},
"prepare-commit-msg": {
"enabled": false,
"actions": []
},
"post-commit": {
"enabled": false,
"actions": []
},
"post-merge": {
"enabled": false,
"actions": []
},
"post-checkout": {
"enabled": false,
"actions": []
},
"post-rewrite": {
"enabled": false,
"actions": []
},
"post-change": {
"enabled": false,
"actions": []
}
}
63 changes: 63 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"name": "infocyph/talkingbytes",
"description": "Communication solution in PHP!",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "abmmhasan",
"email": "abmmhasan@gmail.com"
}
],
"keywords": [
"email",
"smtp"
],
"autoload": {
"psr-4": {
"Infocyph\\TakingBytes\\": "src/"
}
},
"minimum-stability": "stable",
"prefer-stable": true,
"config": {
"sort-packages": true,
"optimize-autoloader": true,
"allow-plugins": {
"pestphp/pest-plugin": true
}
},
"require": {
"php": ">=8.0"
},
"require-dev": {
"captainhook/captainhook": "^5.23",
"laravel/pint": "^1.15",
"pestphp/pest": "^2.34",
"rector/rector": "^1.0",
"symfony/var-dumper": "^7.0"
},
"scripts": {
"test:code": "pest --parallel --processes=10",
"test:refactor": "rector process --dry-run",
"test:lint": "pint --test",
"test:hook": [
"captainhook hook:post-checkout",
"captainhook hook:pre-commit",
"captainhook hook:post-commit",
"captainhook hook:post-merge",
"captainhook hook:post-rewrite",
"captainhook hook:pre-push"
],
"tests": [
"@test:code",
"@test:lint",
"@test:refactor"
],
"git:hook": "captainhook install --only-enabled -nf",
"test": "pest",
"refactor": "rector process",
"lint": "pint",
"post-autoload-dump": "@git:hook"
}
}
17 changes: 17 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.2/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true">
<testsuites>
<testsuite name="Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<coverage/>
<source>
<include>
<directory suffix=".php">./src</directory>
</include>
</source>
</phpunit>
10 changes: 10 additions & 0 deletions pint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"preset": "psr12",
"exclude": [
"tests"
],
"notPath": [
"rector.php",
"test.php"
]
}
20 changes: 20 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Php80\Rector\FunctionLike\MixedTypeRector;
use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([
__DIR__ . '/src'
]);
$rectorConfig->sets([
constant("Rector\Set\ValueObject\LevelSetList::UP_TO_PHP_82")
]);
$rectorConfig->skip([
ReadOnlyPropertyRector::class,
MixedTypeRector::class
]);
};
136 changes: 136 additions & 0 deletions src/Email/Emailer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php

namespace Infocyph\TakingBytes\Email;

use Infocyph\TakingBytes\Email\System\EmailBuilder;
use Infocyph\TakingBytes\Email\System\GenericSender;
use Infocyph\TakingBytes\Email\System\SMTPSender;

class Emailer
{
private $to = [];
private $cc = [];
private $bcc = [];
private $from = [];
private $replyTo;
private $subject;
private $plainText;
private $htmlContent;
private $attachments = [];
private $smtpConfigured = false;
private $smtpConfig = [];

public function __construct($fromEmail, $fromName)
{
$this->from = [
'email' => $this->encodeNonAscii($fromEmail),
'name' => $this->encodeNonAscii($fromName)
];
$this->replyTo = $this->from['email']; // Default Reply-To
}

public function setSMTP(array $smtpConfig)
{
$this->smtpConfig = array_merge([
'host' => '',
'auth' => false,
'username' => '',
'password' => '',
'port' => 25,
'secure' => null
], $smtpConfig);
$this->smtpConfigured = true;
return $this;
}

public function to($email)
{
$this->to[] = $this->encodeNonAscii($email);
return $this;
}

public function cc($email)
{
$this->cc[] = $this->encodeNonAscii($email);
return $this;
}

public function bcc($email)
{
$this->bcc[] = $this->encodeNonAscii($email);
return $this;
}

public function subject($subject)
{
$this->subject = $this->encodeMimeHeader($subject);
return $this;
}

public function plainText($text)
{
$this->plainText = $text;
return $this;
}

public function htmlContent($html)
{
$this->htmlContent = $html;
return $this;
}

public function replyTo($email)
{
$this->replyTo = $this->encodeNonAscii($email);
return $this;
}

public function attachment($filePath, $filename = null)
{
if (file_exists($filePath)) {
$this->attachments[] = ['path' => $filePath, 'name' => $filename ?: basename($filePath)];
}
return $this;
}

public function send()
{
// Instantiate the builder
$builder = new EmailBuilder();

// Build headers using the user-provided input
$headers = $builder->buildHeaders(
$this->from,
$this->cc,
$this->bcc,
$this->replyTo,
$this->attachments
);

// Build the email body (plaintext will be auto-generated if not provided)
$message = $builder->buildBody(
$this->plainText,
$this->htmlContent,
$this->attachments
);

// Choose the appropriate sender method (SMTP or generic)
if ($this->smtpConfigured) {
return (new SMTPSender($this->from, $this->smtpConfig))->send($this->to, $message, $headers);
}
return (new GenericSender())->send($this->to, $this->subject, $message, $headers);
}


private function encodeNonAscii($string)
{
return preg_replace_callback('/[^\x20-\x7E]/', function ($matches) {
return '=?UTF-8?B?' . base64_encode($matches[0]) . '?=';
}, $string);
}

private function encodeMimeHeader($text)
{
return '=?UTF-8?B?' . base64_encode($text) . '?=';
}
}
Loading

0 comments on commit 8b36cb8

Please sign in to comment.