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