11 use Elgg\Traits\Loggable;
13 use Laminas\Mail\Exception\ExceptionInterface;
14 use Laminas\Mail\Header\ContentType;
15 use Laminas\Mail\Message as MailMessage;
16 use Laminas\Mail\Transport\TransportInterface;
17 use Laminas\Mime\Exception\InvalidArgumentException;
18 use Laminas\Mime\Message as MimeMessage;
20 use Laminas\Mime\Part;
46 protected TransportInterface $mailer,
63 $email = $this->events->triggerResults(
'prepare',
'system:email', [],
$email);
65 $msg =
"'prepare','system:email' event handlers should return an instance of " . Email::class;
69 $is_valid =
$email->getFrom() && !empty(
$email->getTo());
70 if (!$this->events->triggerResults(
'validate',
'system:email', [
'email' =>
$email], $is_valid)) {
74 return $this->transport(
$email);
86 if ($this->events->triggerResults(
'transport',
'system:email', [
'email' =>
$email], false)) {
101 'MIME-Version' =>
'1.0',
102 'Content-Transfer-Encoding' =>
'8bit',
111 $message->getHeaders()->addHeaderLine(
"{$name}: {$value}");
117 }
catch (InvalidArgumentException $e) {
118 $this->
getLogger()->error($e->getMessage());
123 $message->setSubject($this->prepareSubject(
$email->getSubject()));
131 $ct =
$message->getHeaders()->get(
'Content-Type');
132 if ($ct instanceof ContentType) {
133 $ct->addParameter(
'format',
'flowed');
138 }
catch (ExceptionInterface $e) {
139 $this->
getLogger()->error($e->getMessage());
172 $multipart = new MimeMessage();
173 $raw_body =
$email->getBody();
174 $message_content_type =
'';
178 $multipart->addPart($plain_text_part);
183 $multipart->addPart($this->makeHtmlPart(
$email));
184 $message_content_type = Mime::MULTIPART_ALTERNATIVE;
193 $multipart_content =
new Part($multipart->generateMessage());
194 $multipart_content->setType(Mime::MULTIPART_ALTERNATIVE);
195 $multipart_content->setBoundary($multipart->getMime()->boundary());
197 $body =
new MimeMessage();
198 $body->addPart($multipart_content);
202 $body->addPart($attachement);
205 $message_content_type = Mime::MULTIPART_MIXED;
210 if (!empty($message_content_type)) {
215 if (!
$header instanceof ContentType) {
219 $header->setType($message_content_type);
220 $header->addParameter(
'boundary',
$body->getMime()->boundary());
236 $mail_params =
$email->getParams();
237 $html_text =
elgg_extract(
'html_message', $mail_params);
238 if ($html_text instanceof Part) {
242 if (is_string($html_text)) {
247 $html_text = $this->html_formatter->inlineCss($html_text,
$css);
250 $html_text = $this->makeHtmlBody([
251 'subject' =>
$email->getSubject(),
258 $html_text = $this->html_formatter->normalizeUrls($html_text);
259 if (empty($html_text)) {
260 return new HtmlPart($html_text);
264 if ($email_html_part_images !==
'base64' && $email_html_part_images !==
'attach') {
265 return new HtmlPart($html_text);
268 $images = $this->findImages($html_text);
269 if (empty($images)) {
270 return new HtmlPart($html_text);
273 if ($email_html_part_images ===
'base64') {
274 foreach ($images as
$url) {
276 $image_url = substr(
$url, 1, -1);
279 $image = $this->image_fetcher->getImage($image_url);
286 $base64image =
$image[
'content-type'] .
';charset=UTF-8;base64,' . base64_encode(
$image[
'data']);
289 $replacement = str_replace($image_url,
"data:{$base64image}",
$url);
292 $html_text = str_replace(
$url, $replacement, $html_text);
295 return new HtmlPart($html_text);
300 foreach ($images as
$url) {
302 $image_url = substr(
$url, 1, -1);
305 $image = $this->image_fetcher->getImage($image_url);
316 $replacement = str_replace($image_url,
"cid:{$uid}",
$url);
318 $html_text = str_replace(
$url, $replacement, $html_text);
323 $message->addPart(
new HtmlPart($html_text));
326 $attachment = Attachment::factory([
328 'content' => $image_data[
'data'],
329 'type' => $image_data[
'content-type'],
330 'filename' => $image_data[
'name'],
331 'encoding' => Mime::ENCODING_BASE64,
332 'disposition' => Mime::DISPOSITION_INLINE,
333 'charset' =>
'UTF-8',
339 $part =
new Part(
$message->generateMessage());
340 $part->setType(Mime::MULTIPART_RELATED);
341 $part->setBoundary(
$message->getMime()->boundary());
365 $options[
'body'] = $this->views->renderView(
'email/elements/body',
$options);
367 $css_views = $this->views->renderView(
'elements/variables.css',
$options);
368 $css_views .= $this->views->renderView(
'email/email.css',
$options);
370 $css_compiled = $this->css_compiler->compile($css_views);
371 $minifier = new \MatthiasMullie\Minify\CSS($css_compiled);
372 $css = $minifier->minify();
376 $html = $this->views->renderView(
'email/elements/html',
$options);
378 return $this->html_formatter->inlineCss(
$html,
$css);
395 $pattern =
'/\ssrc=([\'"]\S+[\'"])/i';
397 preg_match_all($pattern,
$text, $matches);
399 if (empty($matches) || !isset($matches[1])) {
404 return array_unique($matches[1]);
getLogger()
Returns logger.
if(! $user||! $user->canDelete()) $name
$attachments
Outputs attachments.
foreach($categories as $key=> $category) $body
Compile CSS with CSSCrush.
Fetch external images server side.
prepareSubject(string $subject)
Prepare the subject string.
setMessageBody(MailMessage $message, Email $email)
Build the body part of the e-mail message.
makeHtmlBody(array $options=[])
Create the HTML content for use in a HTML email part.
findImages(string $text)
Find img src's in text.
send(Email $email)
Sends an email.
makeHtmlPart(\Elgg\Email $email)
Make the html part of the e-mail message.
__construct(protected Config $config, protected EventsService $events, protected TransportInterface $mailer, protected HtmlFormatter $html_formatter, protected ViewsService $views, protected ImageFetcherService $image_fetcher, protected CssCompiler $css_compiler)
Constructor.
transport(Email $email)
Transports an email.
Plaintext part for email.
Exception thrown if an error which can only be found on runtime occurs.
Support class for MultiPart Mime Messages.
elgg_get_config(string $name, $default=null)
Get an Elgg configuration value.
if($who_can_change_language==='nobody') elseif($who_can_change_language==='admin_only' &&!elgg_is_admin_logged_in()) $options
foreach($periods as $period) $header
foreach($plugin_guids as $guid) if(empty($deactivated_plugins)) $url
$config
Advanced site settings, debugging section.
$subject
HTML body of an email.
elgg_extract($key, $array, $default=null, bool $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
elgg_get_current_language()
Get the current system/user language or 'en'.
elgg_strip_tags(string $string, ?string $allowable_tags=null)
Strip tags and offer plugins the chance.
$html
A wrapper to render a section of the page shell.
if(parse_url(elgg_get_site_url(), PHP_URL_PATH) !=='/') if(file_exists(elgg_get_root_path() . 'robots.txt'))
Set robots.txt.