Merge pull request #8215 from nupplaphil/task/extract_email

Cleanup enotify & Extract System emails
This commit is contained in:
Hypolite Petovan 2020-02-04 15:10:27 -05:00 committed by GitHub
commit e37b1c8794
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 783 additions and 152 deletions

View file

@ -0,0 +1,199 @@
<?php
namespace Friendica\Util\EMailer;
use Exception;
use Friendica\App\BaseURL;
use Friendica\Core\Config\IConfig;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Model\User;
use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Object\Email;
use Friendica\Object\EMail\IEmail;
use Psr\Log\LoggerInterface;
/**
* A base class for building new emails
*/
abstract class MailBuilder
{
/** @var string The default email banner in case nothing else is defined */
const DEFAULT_EMAIL_BANNER = 'images/friendica-32.png';
/** @var L10n */
protected $l10n;
/** @var IConfig */
protected $config;
/** @var BaseURL */
protected $baseUrl;
/** @var LoggerInterface */
protected $logger;
/** @var string */
protected $headers;
/** @var string */
protected $senderName = null;
/** @var string */
protected $senderAddress = null;
/** @var string */
protected $senderNoReply = null;
/** @var string */
protected $recipientAddress = null;
/** @var int */
protected $recipientUid = null;
public function __construct(L10n $l10n, BaseURL $baseUrl, IConfig $config, LoggerInterface $logger)
{
$this->l10n = $l10n;
$this->baseUrl = $baseUrl;
$this->config = $config;
$this->logger = $logger;
$hostname = $baseUrl->getHostname();
if (strpos($hostname, ':')) {
$hostname = substr($hostname, 0, strpos($hostname, ':'));
}
$this->headers = "";
$this->headers .= "Precedence: list\n";
$this->headers .= "X-Friendica-Host: " . $hostname . "\n";
$this->headers .= "X-Friendica-Platform: " . FRIENDICA_PLATFORM . "\n";
$this->headers .= "X-Friendica-Version: " . FRIENDICA_VERSION . "\n";
$this->headers .= "List-ID: <notification." . $hostname . ">\n";
$this->headers .= "List-Archive: <" . $baseUrl->get() . "/notifications/system>\n";
}
/**
* Gets the subject of the concrete builder, which inherits this base class
*
* @return string
*/
abstract protected function getSubject();
/**
* Gets the HTML version of the body of the concrete builder, which inherits this base class
*
* @return string
*/
abstract protected function getHtmlMessage();
/**
* Gets the Plaintext version of the body of the concrete builder, which inherits this base class
*
* @return string
*/
abstract protected function getPlaintextMessage();
/**
* Adds the User ID to the email in case the mail sending needs additional properties of this user
*
* @param array $user The user entity/array, for which the email should be sent
*
* @return static
* @todo Once the user array is replaced with a user entity, replace this array parameter as well
*/
public function forUser(array $user)
{
$this->recipientUid = $user['uid'] ?? 0;
try {
$this->l10n = $user['language'] ? $this->l10n->withLang($user['language']) : $this->l10n;
} catch (Exception $e) {
$this->logger->warning('cannot use language.', ['user' => $user, 'exception' => $e]);
}
return $this;
}
/**
* Adds the sender to the email (if not called/set, the sender will get loaded with the help of the user id)
*
* @param string $name The name of the sender
* @param string $address The (email) address of the sender
* @param string|null $noReply Optional "no-reply" (email) address (if not set, it's the same as the address)
*
* @return static
*/
public function withSender(string $name, string $address, string $noReply = null)
{
$this->senderName = $name;
$this->senderAddress = $address;
$this->senderNoReply = $noReply ?? $this->senderNoReply;
return $this;
}
/**
* Adds a recipient to the email
*
* @param string $address The (email) address of the recipient
*
* @return static
*/
public function withRecipient(string $address)
{
$this->recipientAddress = $address;
return $this;
}
/**
* Build a email based on the given attributes
*
* @param bool $raw True, if the email shouldn't get extended by the default email-template
*
* @return IEmail A new generated email
*
* @throws InternalServerErrorException
* @throws Exception
*/
public function build(bool $raw = false)
{
if ((empty($this->recipientAddress)) &&
!empty($this->recipientUid)) {
$user = User::getById($this->recipientUid, ['email']);
if (!empty($user['email'])) {
$this->recipientAddress = $user['email'];
}
}
if (empty($this->recipientAddress)) {
throw new InternalServerErrorException('Recipient address is missing.');
}
if (empty($this->senderAddress) || empty($this->senderName)) {
throw new InternalServerErrorException('Sender address or name is missing.');
}
$this->senderNoReply = $this->senderNoReply ?? $this->senderAddress;
$msgHtml = $this->getHtmlMessage() ?? '';
if (!$raw) {
// load the template for private message notifications
$tpl = Renderer::getMarkupTemplate('email/html.tpl');
$msgHtml = Renderer::replaceMacros($tpl, [
'$title' => $this->l10n->t('Friendica Notification'),
'$product' => FRIENDICA_PLATFORM,
'$htmlversion' => $msgHtml,
'$sitename' => $this->config->get('config', 'sitename'),
'$banner' => $this->config->get('system', 'email_banner',
$this->baseUrl->get(true) . DIRECTORY_SEPARATOR . self::DEFAULT_EMAIL_BANNER),
]);
}
return new Email(
$this->senderName,
$this->senderAddress,
$this->senderNoReply,
$this->recipientAddress,
$this->getSubject() ?? '',
$msgHtml,
$this->getPlaintextMessage() ?? '',
$this->headers,
$this->recipientUid ?? null);
}
}

View file

@ -0,0 +1,114 @@
<?php
namespace Friendica\Util\EMailer;
use Exception;
use Friendica\App\BaseURL;
use Friendica\Content\Text\BBCode;
use Friendica\Core\Config\IConfig;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Network\HTTPException\InternalServerErrorException;
use Psr\Log\LoggerInterface;
/**
* Builder for system-wide emails without any dependency to concrete entities (like items, activities, ..)
*/
class SystemMailBuilder extends MailBuilder
{
/** @var string */
protected $subject;
/** @var string */
protected $preamble;
/** @var string */
protected $body;
/** @var string */
protected $siteAdmin;
public function __construct(L10n $l10n, BaseURL $baseUrl, IConfig $config, LoggerInterface $logger,
string $siteEmailAddress, string $siteName)
{
parent::__construct($l10n, $baseUrl, $config, $logger);
if ($this->config->get('config', 'admin_name')) {
$this->siteAdmin = $l10n->t('%1$s, %2$s Administrator', $this->config->get('config', 'admin_name'), $siteName);
} else {
$this->siteAdmin = $l10n->t('%s Administrator', $siteName);
}
// Set the system wide site address/name as sender (default for system mails)
$this->senderName = $siteName;
$this->senderAddress = $siteEmailAddress;
$this->senderNoReply = $siteEmailAddress;
}
/**
* Adds a message
*
* @param string $subject The subject of the email
* @param string $preamble The preamble of the email
* @param string|null $body The body of the email (if not set, the preamble will get used as body)
*
* @return static
*/
public function withMessage(string $subject, string $preamble, string $body = null)
{
if (!isset($body)) {
$body = $preamble;
}
$this->subject = $subject;
$this->preamble = $preamble;
$this->body = $body;
return $this;
}
/**
* {@inheritDoc}
*/
protected function getSubject()
{
return $this->subject;
}
/**
* {@inheritDoc}
*
* @throws InternalServerErrorException
* @throws Exception
*/
protected function getHtmlMessage()
{
$htmlVersion = BBCode::convert($this->body);
// load the template for private message notifications
$tpl = Renderer::getMarkupTemplate('email/system/html.tpl');
return Renderer::replaceMacros($tpl, [
'$preamble' => str_replace("\n", "<br>\n", $this->preamble),
'$thanks' => $this->l10n->t('thanks'),
'$site_admin' => $this->siteAdmin,
'$htmlversion' => $htmlVersion,
]);
}
/**
* {@inheritDoc}
*
* @throws Exception
*/
protected function getPlaintextMessage()
{
$textVersion = BBCode::toPlaintext($this->body);
// load the template for private message notifications
$tpl = Renderer::getMarkupTemplate('email/system/text.tpl');
return Renderer::replaceMacros($tpl, [
'$preamble' => $this->preamble,
'$thanks' => $this->l10n->t('thanks'),
'$site_admin' => $this->siteAdmin,
'$textversion' => $textVersion,
]);
}
}

View file

@ -7,10 +7,12 @@ namespace Friendica\Util;
use Friendica\App;
use Friendica\Core\Config\IConfig;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\PConfig\IPConfig;
use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Object\EMail\IEmail;
use Friendica\Protocol\Email;
use Friendica\Util\EMailer\SystemMailBuilder;
use Psr\Log\LoggerInterface;
/**
@ -26,13 +28,65 @@ class Emailer
private $logger;
/** @var App\BaseURL */
private $baseUrl;
/** @var L10n */
private $l10n;
public function __construct(IConfig $config, IPConfig $pConfig, App\BaseURL $baseURL, LoggerInterface $logger)
/** @var string */
private $siteEmailAddress;
/** @var string */
private $siteEmailName;
public function __construct(IConfig $config, IPConfig $pConfig, App\BaseURL $baseURL, LoggerInterface $logger,
L10n $defaultLang)
{
$this->config = $config;
$this->pConfig = $pConfig;
$this->logger = $logger;
$this->baseUrl = $baseURL;
$this->l10n = $defaultLang;
$this->siteEmailAddress = $this->config->get('config', 'sender_email');
if (empty($sysEmailAddress)) {
$hostname = $this->baseUrl->getHostname();
if (strpos($hostname, ':')) {
$hostname = substr($hostname, 0, strpos($hostname, ':'));
}
$this->siteEmailAddress = 'noreply@' . $hostname;
}
$this->siteEmailName = $this->config->get('config', 'sitename', 'Friendica Social Network');
}
/**
* Gets the site's default sender email address
*
* @return string
*/
public function getSiteEmailAddress()
{
return $this->siteEmailAddress;
}
/**
* Gets the site's default sender name
*
* @return string
*/
public function getSiteEmailName()
{
return $this->siteEmailName;
}
/**
* Creates a new system email
*
* @return SystemMailBuilder
*/
public function newSystemMail()
{
return new SystemMailBuilder($this->l10n, $this->baseUrl, $this->config, $this->logger,
$this->getSiteEmailAddress(), $this->getSiteEmailName());
}
/**