, * Nico Hoffmann * @link https://getkirby.com * @copyright Bastian Allgeier * @license https://opensource.org/licenses/MIT */ class Email { use Properties; /** * If set to `true`, the debug mode is enabled * for all emails * * @var bool */ public static $debug = false; /** * Store for sent emails when `Email::$debug` * is set to `true` * * @var array */ public static $emails = []; /** * @var array|null */ protected $attachments; /** * @var \Kirby\Email\Body|null */ protected $body; /** * @var array|null */ protected $bcc; /** * @var \Closure|null */ protected $beforeSend; /** * @var array|null */ protected $cc; /** * @var string|null */ protected $from; /** * @var string|null */ protected $fromName; /** * @var string|null */ protected $replyTo; /** * @var string|null */ protected $replyToName; /** * @var bool */ protected $isSent = false; /** * @var string|null */ protected $subject; /** * @var array|null */ protected $to; /** * @var array|null */ protected $transport; /** * Email constructor * * @param array $props * @param bool $debug */ public function __construct(array $props = [], bool $debug = false) { $this->setProperties($props); // @codeCoverageIgnoreStart if (static::$debug === false && $debug === false) { $this->send(); } elseif (static::$debug === true) { static::$emails[] = $this; } // @codeCoverageIgnoreEnd } /** * Returns the email attachments * * @return array */ public function attachments(): array { return $this->attachments; } /** * Returns the email body * * @return \Kirby\Email\Body|null */ public function body() { return $this->body; } /** * Returns "bcc" recipients * * @return array */ public function bcc(): array { return $this->bcc; } /** * Returns the beforeSend callback closure, * which has access to the PHPMailer instance * * @return \Closure|null */ public function beforeSend(): ?Closure { return $this->beforeSend; } /** * Returns "cc" recipients * * @return array */ public function cc(): array { return $this->cc; } /** * Returns default transport settings * * @return array */ protected function defaultTransport(): array { return [ 'type' => 'mail' ]; } /** * Returns the "from" email address * * @return string */ public function from(): string { return $this->from; } /** * Returns the "from" name * * @return string|null */ public function fromName(): ?string { return $this->fromName; } /** * Checks if the email has an HTML body * * @return bool */ public function isHtml() { return empty($this->body()->html()) === false; } /** * Checks if the email has been sent successfully * * @return bool */ public function isSent(): bool { return $this->isSent; } /** * Returns the "reply to" email address * * @return string */ public function replyTo(): string { return $this->replyTo; } /** * Returns the "reply to" name * * @return string|null */ public function replyToName(): ?string { return $this->replyToName; } /** * Converts single or multiple email addresses to a sanitized format * * @param string|array|null $email * @param bool $multiple * @return array|mixed|string * @throws \Exception */ protected function resolveEmail($email = null, bool $multiple = true) { if ($email === null) { return $multiple === true ? [] : ''; } if (is_array($email) === false) { $email = [$email => null]; } $result = []; foreach ($email as $address => $name) { // convert simple email arrays to associative arrays if (is_int($address) === true) { // the value is the address, there is no name $address = $name; $result[$address] = null; } else { $result[$address] = $name; } // ensure that the address is valid if (V::email($address) === false) { throw new Exception(sprintf('"%s" is not a valid email address', $address)); } } return $multiple === true ? $result : array_keys($result)[0]; } /** * Sends the email * * @return bool */ public function send(): bool { return $this->isSent = true; } /** * Sets the email attachments * * @param array|null $attachments * @return $this */ protected function setAttachments($attachments = null) { $this->attachments = $attachments ?? []; return $this; } /** * Sets the email body * * @param string|array $body * @return $this */ protected function setBody($body) { if (is_string($body) === true) { $body = ['text' => $body]; } $this->body = new Body($body); return $this; } /** * Sets "bcc" recipients * * @param string|array|null $bcc * @return $this */ protected function setBcc($bcc = null) { $this->bcc = $this->resolveEmail($bcc); return $this; } /** * Sets the "beforeSend" callback * * @param \Closure|null $beforeSend * @return $this */ protected function setBeforeSend(?Closure $beforeSend = null) { $this->beforeSend = $beforeSend; return $this; } /** * Sets "cc" recipients * * @param string|array|null $cc * @return $this */ protected function setCc($cc = null) { $this->cc = $this->resolveEmail($cc); return $this; } /** * Sets the "from" email address * * @param string $from * @return $this */ protected function setFrom(string $from) { $this->from = $this->resolveEmail($from, false); return $this; } /** * Sets the "from" name * * @param string|null $fromName * @return $this */ protected function setFromName(string $fromName = null) { $this->fromName = $fromName; return $this; } /** * Sets the "reply to" email address * * @param string|null $replyTo * @return $this */ protected function setReplyTo(string $replyTo = null) { $this->replyTo = $this->resolveEmail($replyTo, false); return $this; } /** * Sets the "reply to" name * * @param string|null $replyToName * @return $this */ protected function setReplyToName(string $replyToName = null) { $this->replyToName = $replyToName; return $this; } /** * Sets the email subject * * @param string $subject * @return $this */ protected function setSubject(string $subject) { $this->subject = $subject; return $this; } /** * Sets the recipients of the email * * @param string|array $to * @return $this */ protected function setTo($to) { $this->to = $this->resolveEmail($to); return $this; } /** * Sets the email transport settings * * @param array|null $transport * @return $this */ protected function setTransport($transport = null) { $this->transport = $transport; return $this; } /** * Returns the email subject * * @return string */ public function subject(): string { return $this->subject; } /** * Returns the email recipients * * @return array */ public function to(): array { return $this->to; } /** * Returns the email transports settings * * @return array */ public function transport(): array { return $this->transport ?? $this->defaultTransport(); } }