RprtCli/app/src/Utils/Mailer/MailerService.php

207 lines
5.9 KiB
PHP

<?php
declare(strict_types=1);
// src/Utils/Mailer/MailerService.php
namespace RprtCli\Utils\Mailer;
use Exception;
use RprtCli\Utils\Configuration\ConfigurationInterface;
use RprtCli\Utils\PdfExport\PdfExportInterface;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mime\Email;
use function date;
use function explode;
use function fgets;
use function file_exists;
use function rawurlencode;
use function readline;
use function strtotime;
use function system;
use function trim;
use function var_dump;
use const STDIN;
/**
* Send emails with invoices as attachments.
*
* https://symfony.com/doc/current/mailer.html
*/
class MailerService implements MailerInterface
{
protected $config;
protected $pdf;
// Data properties.
protected $to;
protected $subject;
protected $text;
protected $attachment;
protected $templatePath;
protected $email;
public function __construct(ConfigurationInterface $config, PdfExportInterface $pdf)
{
$this->config = $config;
$this->pdf = $pdf;
}
public function setRecipients(array $to): void
{
$this->to = $to;
}
public function setSubject(string $subject): void
{
$this->subject = $subject;
}
public function setAttachment(string $path): void
{
// @TODO - add some error handling.
$this->attachment = $path;
}
public function getProperty(string $property)
{
// Only for simple value properies - string and numbers.
// from, to, subject.
if (! isset($this->{$property})) {
$value = $this->config->get('email.' . $property, false);
if (! $value) {
$value = readline("Property {$property} is not configured. Enter value: ");
}
$this->{$property} = $value;
}
return $this->{$property};
}
protected function getRecipients()
{
if (! isset($this->to)) {
$value = $this->config->get('email.to', false);
if (! $value) {
$value = explode(',', readline('Provide recipients\' emails separated by a comma: '));
}
$this->to = $value;
}
return $this->to;
}
private function readPassword($prompt = "Enter Password:")
{
echo $prompt;
system('stty -echo');
$password = trim(fgets(STDIN));
system('stty echo');
return $password;
}
protected function getPasswordProperty()
{
if (! isset($this->password)) {
$value = $this->config->get('email.password', false);
if (! $value) {
$value = $this->readPassword();
}
$this->password = $value;
}
return $this->password;
}
public function sendMail(string $from, array $to, string $subject, string $text, array $attachment = []): void
{
$email = new Email();
$email->from($from);
$email->to(...$to);
// @TODO use twig for templates. Create new template service.
// https://github.com/symfony/mailer
$email->subject($subject);
$email->text($text);
if (! empty($attachment)) {
if (! isset($attachment['path'])) {
var_dump('Attachment path missing!');
} else {
$email->attachFromPath($attachment['path'], $attachment['name'] ?? null, $attachment['type'] ?? null);
}
}
// Not sure whether it would be nicer to use class property instead of variable.
$transport = $this->getTransport();
$mailer = $this->getMailer($transport);
$mailer->send($email);
}
public function getTransport()
{
// @TODO remove username and password from config.
$username = rawurlencode($this->getProperty('username'));
$password = rawurlencode($this->getPasswordProperty());
// If your credentials contain special characters, you must URL-encode them.
// $mailer_dsn = "gmail+smtp://{$username}:{$password}@default";
$mailer_dsn = "gmail://{$username}:{$password}@localhost?encryption=tls&auth_mode=oauth";
return Transport::fromDsn($mailer_dsn);
}
public function getMailer($transport)
{
return new Mailer($transport);
}
public function sendDefaultMail(string $output): void
{
$tokens = $this->pdf->gatherTokensForTemplate(
$this->getEmailTemplatePath(),
false,
$this->getDefaultTokens(),
'email.tokens'
);
$text = $this->pdf->replaceTokensInTemplate($this->getEmailTemplatePath(), $tokens);
$this->sendMail(
$this->getProperty('from'),
$this->getProperty('to'),
$this->getProperty('subject'),
$text,
['path' => $output, 'Invoice', 'application/pdf']
);
}
public function getDefaultTokens(): array
{
$tokens = [];
$date = strtotime('-1 month');
$tokens['month'] = date('F', $date);
$tokens['year'] = date('Y', $date);
return $tokens;
}
protected function getEmailTemplatePath(): ?string
{
if (! isset($this->templatePath)) {
$template_path = $this->config->get('email.template_path', false);
if (! $template_path) {
$template_path = readline('Enter template file path: ');
}
if (! file_exists($template_path)) {
throw new Exception('Template file not found!');
}
$this->templatePath = $template_path;
}
return $this->templatePath;
}
public function setEmailTemplatePath(string $path): void
{
if (file_exists($path)) {
$this->templatePath = $path;
return;
}
throw new Exception('Email template file not found!');
}
}