]> git.mxchange.org Git - friendica.git/blob - src/Util/EMailer/MailBuilder.php
1310fee8748cef2005cf877ccaf701dd88d7ac5e
[friendica.git] / src / Util / EMailer / MailBuilder.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2023, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Util\EMailer;
23
24 use Exception;
25 use Friendica\App;
26 use Friendica\App\BaseURL;
27 use Friendica\Core\Config\Capability\IManageConfigValues;
28 use Friendica\Core\L10n;
29 use Friendica\Core\Renderer;
30 use Friendica\Model\User;
31 use Friendica\Network\HTTPException\UnprocessableEntityException;
32 use Friendica\Object\Email;
33 use Friendica\Object\EMail\IEmail;
34 use Psr\Log\LoggerInterface;
35
36 /**
37  * A base class for building new emails
38  */
39 abstract class MailBuilder
40 {
41         /** @var string The default email banner in case nothing else is defined */
42         const DEFAULT_EMAIL_BANNER = 'images/friendica-32.png';
43
44         /** @var L10n */
45         protected $l10n;
46         /** @var IManageConfigValues */
47         protected $config;
48         /** @var BaseURL */
49         protected $baseUrl;
50         /** @var LoggerInterface */
51         protected $logger;
52
53         /** @var string[][] */
54         protected $headers;
55
56         /** @var string */
57         protected $senderName = null;
58         /** @var string */
59         protected $senderAddress = null;
60         /** @var string */
61         protected $senderNoReply = null;
62
63         /** @var string */
64         protected $recipientAddress = null;
65         /** @var int */
66         protected $recipientUid = null;
67
68         public function __construct(L10n $l10n, BaseURL $baseUrl, IManageConfigValues $config, LoggerInterface $logger)
69         {
70                 $this->l10n    = $l10n;
71                 $this->baseUrl = $baseUrl;
72                 $this->config  = $config;
73                 $this->logger  = $logger;
74
75                 $hostname = $baseUrl->getHostname();
76                 if (strpos($hostname, ':')) {
77                         $hostname = substr($hostname, 0, strpos($hostname, ':'));
78                 }
79
80                 $this->headers = [
81                         'Precedence'           => ['list'],
82                         'X-Friendica-Host'     => [$hostname],
83                         'X-Friendica-Platform' => [App::PLATFORM],
84                         'X-Friendica-Version'  => [App::VERSION],
85                         'List-ID'              => ['<notification.' . $hostname . '>'],
86                         'List-Archive'         => ['<' . $baseUrl->get() . '/notifications/system>'],
87                 ];
88         }
89
90         /**
91          * Gets the subject of the concrete builder, which inherits this base class
92          *
93          * @return string
94          */
95         abstract protected function getSubject();
96
97         /**
98          * Gets the HTML version of the body of the concrete builder, which inherits this base class
99          *
100          * @return string
101          */
102         abstract protected function getHtmlMessage();
103
104         /**
105          * Gets the Plaintext version of the body of the concrete builder, which inherits this base class
106          *
107          * @return string
108          */
109         abstract protected function getPlaintextMessage();
110
111         /**
112          * Adds the User ID to the email in case the mail sending needs additional properties of this user
113          *
114          * @param array $user The user entity/array, for which the email should be sent
115          *
116          * @return static
117          * @todo Once the user array is replaced with a user entity, replace this array parameter as well
118          */
119         public function forUser(array $user)
120         {
121                 $this->recipientUid = $user['uid'] ?? 0;
122                 try {
123                         $this->l10n = isset($user['language']) ? $this->l10n->withLang($user['language']) : $this->l10n;
124                 } catch (Exception $e) {
125                         $this->logger->warning('cannot use language.', ['user' => $user, 'exception' => $e]);
126                 }
127
128                 return $this;
129         }
130
131         /**
132          * Adds the sender to the email (if not called/set, the sender will get loaded with the help of the user id)
133          *
134          * @param string      $name    The name of the sender
135          * @param string      $address The (email) address of the sender
136          * @param string|null $noReply Optional "no-reply" (email) address (if not set, it's the same as the address)
137          *
138          * @return static
139          */
140         public function withSender(string $name, string $address, string $noReply = null)
141         {
142                 $this->senderName    = $name;
143                 $this->senderAddress = $address;
144                 $this->senderNoReply = $noReply ?? $this->senderNoReply;
145
146                 return $this;
147         }
148
149         /**
150          * Adds a recipient to the email
151          *
152          * @param string $address The (email) address of the recipient
153          *
154          * @return static
155          */
156         public function withRecipient(string $address)
157         {
158                 $this->recipientAddress = $address;
159
160                 return $this;
161         }
162
163         /**
164          * Returns the current headers
165          *
166          * @return string[][]
167          */
168         public function getHeaders(): array
169         {
170                 return $this->headers;
171         }
172
173         /**
174          * Sets the headers
175          *
176          * Expected format is
177          * [
178          *   'Header1' => ['value1', 'value2', ...],
179          *   'Header2' => ['value3', 'value4', ...],
180          *   ...
181          * ]
182          *
183          * @param string[][] $headers
184          * @return $this
185          */
186         public function withHeaders(array $headers): MailBuilder
187         {
188                 $this->headers = $headers;
189
190                 return $this;
191         }
192
193         /**
194          * Adds a value to a header
195          *
196          * @param string $name The header name
197          * @param string $value The value of the header to add
198          *
199          * @return static
200          */
201         public function addHeader(string $name, string $value)
202         {
203                 $this->headers[$name][] = $value;
204
205                 return $this;
206         }
207
208         /**
209          * Sets a value to a header (overwrites existing values)
210          *
211          * @param string $name The header name
212          * @param string $value The value to set
213          *
214          * @return static
215          */
216         public function setHeader(string $name, string $value)
217         {
218                 $this->headers[$name] = [$value];
219
220                 return $this;
221         }
222
223         /**
224          * Build a email based on the given attributes
225          *
226          * @param bool $raw True, if the email shouldn't get extended by the default email-template
227          *
228          * @return IEmail A new generated email
229          *
230          * @throws UnprocessableEntityException
231          * @throws Exception
232          */
233         public function build(bool $raw = false)
234         {
235                 if ((empty($this->recipientAddress)) &&
236                     !empty($this->recipientUid)) {
237                         $user = User::getById($this->recipientUid, ['email']);
238
239                         if (!empty($user['email'])) {
240                                 $this->recipientAddress = $user['email'];
241                         }
242                 }
243
244                 if (empty($this->recipientAddress)) {
245                         throw new UnprocessableEntityException('Recipient address is missing.');
246                 }
247
248                 if (empty($this->senderAddress) || empty($this->senderName)) {
249                         throw new UnprocessableEntityException('Sender address or name is missing.');
250                 }
251
252                 $this->senderNoReply = $this->senderNoReply ?? $this->senderAddress;
253
254                 $msgHtml = $this->getHtmlMessage() ?? '';
255
256                 if (!$raw) {
257                         // load the template for private message notifications
258                         $tpl     = Renderer::getMarkupTemplate('email/html.tpl');
259                         $msgHtml = Renderer::replaceMacros($tpl, [
260                                 '$title'       => $this->l10n->t('Friendica Notification'),
261                                 '$product'     => App::PLATFORM,
262                                 '$htmlversion' => $msgHtml,
263                                 '$sitename'    => $this->config->get('config', 'sitename'),
264                                 '$banner'      => $this->config->get('system', 'email_banner',
265                                         $this->baseUrl->get(true) . DIRECTORY_SEPARATOR . self::DEFAULT_EMAIL_BANNER),
266                         ]);
267                 }
268
269                 return new Email(
270                         $this->senderName,
271                         $this->senderAddress,
272                         $this->senderNoReply,
273                         $this->recipientAddress,
274                         $this->getSubject() ?? '',
275                         $msgHtml,
276                         $this->getPlaintextMessage() ?? '',
277                         $this->headers,
278                         $this->recipientUid ?? null);
279         }
280 }