mirror of
https://github.com/nextcloud/server.git
synced 2024-11-14 12:26:49 +00:00
dae7c159f7
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
323 lines
8.2 KiB
PHP
323 lines
8.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
/**
|
|
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
|
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
namespace OC\Mail;
|
|
|
|
use OCP\Mail\Headers\AutoSubmitted;
|
|
use OCP\Mail\IAttachment;
|
|
use OCP\Mail\IEMailTemplate;
|
|
use OCP\Mail\IMessage;
|
|
use Symfony\Component\Mime\Address;
|
|
use Symfony\Component\Mime\Email;
|
|
use Symfony\Component\Mime\Exception\InvalidArgumentException;
|
|
use Symfony\Component\Mime\Exception\RfcComplianceException;
|
|
|
|
/**
|
|
* Class Message provides a wrapper around Symfony\Component\Mime\Email (Used to be around SwiftMail)
|
|
*
|
|
* @package OC\Mail
|
|
*/
|
|
class Message implements IMessage {
|
|
private array $to = [];
|
|
private array $from = [];
|
|
private array $replyTo = [];
|
|
private array $cc = [];
|
|
private array $bcc = [];
|
|
|
|
public function __construct(
|
|
private Email $symfonyEmail,
|
|
private bool $plainTextOnly,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* @since 13.0.0
|
|
* @return $this
|
|
*/
|
|
public function attach(IAttachment $attachment): IMessage {
|
|
/** @var Attachment $attachment */
|
|
$attachment->attach($this->symfonyEmail);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Can be used to "attach content inline" as message parts with specific MIME type and encoding.
|
|
* {@inheritDoc}
|
|
* @since 26.0.0
|
|
*/
|
|
public function attachInline(string $body, string $name, ?string $contentType = null): IMessage {
|
|
# To be sure this works with iCalendar messages, we encode with 8bit instead of
|
|
# quoted-printable encoding. We save the current encoder, replace the current
|
|
# encoder with an 8bit encoder and after we've finished, we reset the encoder
|
|
# to the previous one. Originally intended to be added after the message body,
|
|
# as it is curently unknown if all mail clients handle this properly if added
|
|
# before.
|
|
$this->symfonyEmail->embed($body, $name, $contentType);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Converts the [['displayName' => 'email'], ['displayName2' => 'email2']] arrays to valid Adresses
|
|
*
|
|
* @param array $addresses Array of mail addresses
|
|
* @return Address[]
|
|
* @throws RfcComplianceException|InvalidArgumentException
|
|
*/
|
|
protected function convertAddresses(array $addresses): array {
|
|
$convertedAddresses = [];
|
|
|
|
if (empty($addresses)) {
|
|
return [];
|
|
}
|
|
|
|
array_walk($addresses, function ($readableName, $email) use (&$convertedAddresses) {
|
|
if (is_numeric($email)) {
|
|
$convertedAddresses[] = new Address($readableName);
|
|
} else {
|
|
$convertedAddresses[] = new Address($email, $readableName);
|
|
}
|
|
});
|
|
|
|
return $convertedAddresses;
|
|
}
|
|
|
|
/**
|
|
* Set the from address of this message.
|
|
*
|
|
* If no "From" address is used \OC\Mail\Mailer will use mail_from_address and mail_domain from config.php
|
|
*
|
|
* @param array $addresses Example: array('sender@domain.org', 'other@domain.org' => 'A name')
|
|
* @return $this
|
|
*/
|
|
public function setFrom(array $addresses): IMessage {
|
|
$this->from = $addresses;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the from address of this message.
|
|
*/
|
|
public function getFrom(): array {
|
|
return $this->from;
|
|
}
|
|
|
|
/**
|
|
* Set the Reply-To address of this message
|
|
* @return $this
|
|
*/
|
|
public function setReplyTo(array $addresses): IMessage {
|
|
$this->replyTo = $addresses;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Returns the Reply-To address of this message
|
|
*/
|
|
public function getReplyTo(): array {
|
|
return $this->replyTo;
|
|
}
|
|
|
|
/**
|
|
* Set the to addresses of this message.
|
|
*
|
|
* @param array $recipients Example: array('recipient@domain.org', 'other@domain.org' => 'A name')
|
|
* @return $this
|
|
*/
|
|
public function setTo(array $recipients): IMessage {
|
|
$this->to = $recipients;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the to address of this message.
|
|
*/
|
|
public function getTo(): array {
|
|
return $this->to;
|
|
}
|
|
|
|
/**
|
|
* Set the CC recipients of this message.
|
|
*
|
|
* @param array $recipients Example: array('recipient@domain.org', 'other@domain.org' => 'A name')
|
|
* @return $this
|
|
*/
|
|
public function setCc(array $recipients): IMessage {
|
|
$this->cc = $recipients;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the cc address of this message.
|
|
*/
|
|
public function getCc(): array {
|
|
return $this->cc;
|
|
}
|
|
|
|
/**
|
|
* Set the BCC recipients of this message.
|
|
*
|
|
* @param array $recipients Example: array('recipient@domain.org', 'other@domain.org' => 'A name')
|
|
* @return $this
|
|
*/
|
|
public function setBcc(array $recipients): IMessage {
|
|
$this->bcc = $recipients;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the Bcc address of this message.
|
|
*/
|
|
public function getBcc(): array {
|
|
return $this->bcc;
|
|
}
|
|
|
|
/**
|
|
* @return $this
|
|
*/
|
|
public function setSubject(string $subject): IMessage {
|
|
$this->symfonyEmail->subject($subject);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the from subject of this message.
|
|
*/
|
|
public function getSubject(): string {
|
|
return $this->symfonyEmail->getSubject() ?? '';
|
|
}
|
|
|
|
/**
|
|
* @return $this
|
|
*/
|
|
public function setPlainBody(string $body): IMessage {
|
|
$this->symfonyEmail->text($body);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the plain body of this message.
|
|
*/
|
|
public function getPlainBody(): string {
|
|
/** @var string $body */
|
|
$body = $this->symfonyEmail->getTextBody() ?? '';
|
|
return $body;
|
|
}
|
|
|
|
/**
|
|
* @return $this
|
|
*/
|
|
public function setHtmlBody(string $body): IMessage {
|
|
if (!$this->plainTextOnly) {
|
|
$this->symfonyEmail->html($body);
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the underlying Email instance
|
|
*/
|
|
public function setSymfonyEmail(Email $symfonyEmail): void {
|
|
$this->symfonyEmail = $symfonyEmail;
|
|
}
|
|
|
|
/**
|
|
* Get the underlying Email instance
|
|
*/
|
|
public function getSymfonyEmail(): Email {
|
|
return $this->symfonyEmail;
|
|
}
|
|
|
|
/**
|
|
* @return $this
|
|
*/
|
|
public function setBody(string $body, string $contentType): IMessage {
|
|
if (!$this->plainTextOnly || $contentType !== 'text/html') {
|
|
if ($contentType === 'text/html') {
|
|
$this->symfonyEmail->html($body);
|
|
} else {
|
|
$this->symfonyEmail->text($body);
|
|
}
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the recipients on the symphony email
|
|
*
|
|
* Since
|
|
*
|
|
* setTo
|
|
* setFrom
|
|
* setReplyTo
|
|
* setCc
|
|
* setBcc
|
|
*
|
|
* could throw a \Symfony\Component\Mime\Exception\RfcComplianceException
|
|
* or a \Symfony\Component\Mime\Exception\InvalidArgumentException
|
|
* we wrap the calls here. We then have the validation errors all in one place and can
|
|
* throw shortly before \OC\Mail\Mailer::send
|
|
*
|
|
* @throws InvalidArgumentException|RfcComplianceException
|
|
*/
|
|
public function setRecipients(): void {
|
|
$this->symfonyEmail->to(...$this->convertAddresses($this->getTo()));
|
|
$this->symfonyEmail->from(...$this->convertAddresses($this->getFrom()));
|
|
$this->symfonyEmail->replyTo(...$this->convertAddresses($this->getReplyTo()));
|
|
$this->symfonyEmail->cc(...$this->convertAddresses($this->getCc()));
|
|
$this->symfonyEmail->bcc(...$this->convertAddresses($this->getBcc()));
|
|
}
|
|
|
|
/**
|
|
* @return $this
|
|
*/
|
|
public function useTemplate(IEMailTemplate $emailTemplate): IMessage {
|
|
$this->setSubject($emailTemplate->renderSubject());
|
|
$this->setPlainBody($emailTemplate->renderText());
|
|
if (!$this->plainTextOnly) {
|
|
$this->setHtmlBody($emailTemplate->renderHtml());
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Add the Auto-Submitted header to the email, preventing most automated
|
|
* responses to automated messages.
|
|
*
|
|
* @param AutoSubmitted::VALUE_* $value (one of AutoSubmitted::VALUE_NO, AutoSubmitted::VALUE_AUTO_GENERATED, AutoSubmitted::VALUE_AUTO_REPLIED)
|
|
* @return $this
|
|
*/
|
|
public function setAutoSubmitted(string $value): IMessage {
|
|
$headers = $this->symfonyEmail->getHeaders();
|
|
|
|
if ($headers->has(AutoSubmitted::HEADER)) {
|
|
// if the header already exsists, remove it.
|
|
// the value can be modified with some implementations
|
|
// of the interface \Swift_Mime_Header, however the
|
|
// interface doesn't, and this makes the static-code
|
|
// analysis unhappy.
|
|
// @todo check if symfony mailer can modify the autosubmitted header
|
|
$headers->remove(AutoSubmitted::HEADER);
|
|
}
|
|
|
|
$headers->addTextHeader(AutoSubmitted::HEADER, $value);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the current value of the Auto-Submitted header. Defaults to "no"
|
|
* which is equivalent to the header not existing at all
|
|
*/
|
|
public function getAutoSubmitted(): string {
|
|
$headers = $this->symfonyEmail->getHeaders();
|
|
|
|
return $headers->has(AutoSubmitted::HEADER) ?
|
|
$headers->get(AutoSubmitted::HEADER)->getBodyAsString() : AutoSubmitted::VALUE_NO;
|
|
}
|
|
}
|