diff options
author | Lukas Reschke <lukas@owncloud.com> | 2015-02-12 13:53:27 +0100 |
---|---|---|
committer | Lukas Reschke <lukas@owncloud.com> | 2015-03-16 12:47:05 +0100 |
commit | 13486a5ada62e4355473ca01e07371c162951e84 (patch) | |
tree | c079e9c53691ca14e5e1898c40a93322d6e727f5 /lib/private/mail | |
parent | 0d9f149dd93997085b85e2b174f5989a1b996263 (diff) | |
download | nextcloud-server-13486a5ada62e4355473ca01e07371c162951e84.tar.gz nextcloud-server-13486a5ada62e4355473ca01e07371c162951e84.zip |
Migrate to SwiftMail
Replaces the OC_Mail and phpmailer with SwiftMail allowing us to mock it properly.
Fixes the unit test execution on master on local machines and https://github.com/owncloud/core/issues/12014
Conflicts:
3rdparty
lib/private/server.php
lib/public/iservercontainer.php
tests/lib/mail.php
tests/settings/controller/mailsettingscontrollertest.php
Conflicts:
3rdparty
lib/private/mail.php
lib/private/server.php
lib/public/iservercontainer.php
settings/ajax/lostpassword.php
settings/application.php
Diffstat (limited to 'lib/private/mail')
-rw-r--r-- | lib/private/mail/mailer.php | 154 | ||||
-rw-r--r-- | lib/private/mail/message.php | 206 | ||||
-rw-r--r-- | lib/private/mail/util.php | 45 |
3 files changed, 405 insertions, 0 deletions
diff --git a/lib/private/mail/mailer.php b/lib/private/mail/mailer.php new file mode 100644 index 00000000000..ff4b0a0ef62 --- /dev/null +++ b/lib/private/mail/mailer.php @@ -0,0 +1,154 @@ +<?php +/** + * Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Mail; + +use OCP\IConfig; +use OCP\Mail\IMailer; + +/** + * Class Mailer provides some basic functions to create a mail message that can be used in combination with + * \OC\Mail\Message. + * + * Example usage: + * + * $mailer = \OC::$server->getMailer(); + * $message = $mailer->createMessage(); + * $message->setSubject('Your Subject'); + * $message->setFrom(array('cloud@domain.org' => 'ownCloud Notifier'); + * $message->setTo(array('recipient@domain.org' => 'Recipient'); + * $message->setBody('The message text'); + * $mailer->send($message); + * + * This message can then be passed to send() of \OC\Mail\Mailer + * + * @package OC\Mail + */ +class Mailer implements IMailer { + /** @var \Swift_SmtpTransport|\Swift_SendmailTransport|\Swift_MailTransport Cached transport */ + private $instance = null; + /** @var IConfig */ + private $config; + /** @var \OC_Defaults */ + private $defaults; + + /** + * @param IConfig $config + * @param \OC_Defaults $defaults + */ + function __construct(IConfig $config, \OC_Defaults $defaults) { + $this->config = $config; + $this->defaults = $defaults; + } + + /** + * Creates a new message object that can be passed to send() + * + * @return Message + */ + public function createMessage() { + return new Message(new \Swift_Message()); + } + + /** + * Send the specified message. Also sets the from address to the value defined in config.php + * if no-one has been passed. + * + * @param Message $message Message to send + * @return string[] Array with failed recipients. Be aware that this depends on the used mail backend and + * therefore should be considered + * @throws \Exception In case it was not possible to send the message. (for example if an invalid mail address + * has been supplied.) + */ + public function send(Message $message) { + if (sizeof($message->getFrom()) === 0) { + $message->setFrom(array(\OCP\Util::getDefaultEmailAddress($this->defaults->getName()))); + } + + $failedRecipients = array(); + + $this->getInstance()->send($message->getSwiftMessage(), $failedRecipients); + + return $failedRecipients; + } + + /** + * Returns whatever transport is configured within the config + * + * @return \Swift_SmtpTransport|\Swift_SendmailTransport|\Swift_MailTransport + */ + protected function getInstance() { + if (!is_null($this->instance)) { + return $this->instance; + } + + switch ($this->config->getSystemValue('mail_smtpmode', 'php')) { + case 'smtp': + $this->instance = $this->getSMTPInstance(); + break; + case 'sendmail': + $this->instance = $this->getSendMailInstance(); + break; + default: + $this->instance = $this->getMailInstance(); + break; + } + + return $this->instance; + } + + /** + * Returns the SMTP transport + * + * @return \Swift_SmtpTransport + */ + protected function getSmtpInstance() { + $transport = \Swift_SmtpTransport::newInstance(); + $transport->setTimeout($this->config->getSystemValue('mail_smtptimeout', 10)); + $transport->setHost($this->config->getSystemValue('mail_smtphost', '127.0.0.1')); + $transport->setPort($this->config->getSystemValue('mail_smtpport', 25)); + if ($this->config->getSystemValue('mail_smtpauth', false)) { + $transport->setUsername($this->config->getSystemValue('mail_smtpname', '')); + $transport->setPassword($this->config->getSystemValue('mail_smtppassword', '')); + $transport->setAuthMode($this->config->getSystemValue('mail_smtpauthtype', 'LOGIN')); + } + $smtpSecurity = $this->config->getSystemValue('mail_smtpsecure', ''); + if (!empty($smtpSecurity)) { + $transport->setEncryption($smtpSecurity); + } + return $transport; + } + + /** + * Returns the sendmail transport + * + * @return \Swift_SendmailTransport + */ + protected function getSendMailInstance() { + switch ($this->config->getSystemValue('mail_smtpmode', 'sendmail')) { + case 'qmail': + $binaryPath = '/var/qmail/bin/sendmail'; + break; + default: + $binaryPath = '/usr/sbin/sendmail'; + break; + } + + return \Swift_SendmailTransport::newInstance($binaryPath . ' -bs'); + } + + /** + * Returns the mail transport + * + * @return \Swift_MailTransport + */ + protected function getMailInstance() { + return \Swift_MailTransport::newInstance(); + } + +} diff --git a/lib/private/mail/message.php b/lib/private/mail/message.php new file mode 100644 index 00000000000..60700196c5f --- /dev/null +++ b/lib/private/mail/message.php @@ -0,0 +1,206 @@ +<?php +/** + * Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Mail; + +use Swift_Message; + +/** + * Class Message provides a wrapper around SwiftMail + * + * @package OC\Mail + */ +class Message { + /** @var Swift_Message */ + private $swiftMessage; + + /** + * @param Swift_Message $swiftMessage + */ + function __construct(Swift_Message $swiftMessage) { + $this->swiftMessage = $swiftMessage; + } + + /** + * SwiftMailer does currently not work with IDN domains, this function therefore converts the domains + * FIXME: Remove this once SwiftMailer supports IDN + * + * @param array $addresses Array of mail addresses, key will get converted + * @return array Converted addresses if `idn_to_ascii` exists + */ + protected function convertAddresses($addresses) { + if (!function_exists('idn_to_ascii')) { + return $addresses; + } + + $convertedAddresses = array(); + + foreach($addresses as $email => $readableName) { + if(!is_numeric($email)) { + list($name, $domain) = explode('@', $email, 2); + $domain = idn_to_ascii($domain); + $convertedAddresses[$name.'@'.$domain] = $readableName; + } else { + list($name, $domain) = explode('@', $readableName, 2); + $domain = idn_to_ascii($domain); + $convertedAddresses[$email] = $name.'@'.$domain; + } + } + + 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) { + $addresses = $this->convertAddresses($addresses); + + $this->swiftMessage->setFrom($addresses); + return $this; + } + + /** + * Get the from address of this message. + * + * @return array + */ + public function getFrom() { + return $this->swiftMessage->getFrom(); + } + + /** + * 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) { + $recipients = $this->convertAddresses($recipients); + + $this->swiftMessage->setTo($recipients); + return $this; + } + + /** + * Get the to address of this message. + * + * @return array + */ + public function getTo() { + return $this->swiftMessage->getTo(); + } + + /** + * 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) { + $recipients = $this->convertAddresses($recipients); + + $this->swiftMessage->setCc($recipients); + return $this; + } + + /** + * Get the cc address of this message. + * + * @return array + */ + public function getCc() { + return $this->swiftMessage->getCc(); + } + + /** + * 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) { + $recipients = $this->convertAddresses($recipients); + + $this->swiftMessage->setBcc($recipients); + return $this; + } + + /** + * Get the Bcc address of this message. + * + * @return array + */ + public function getBcc() { + return $this->swiftMessage->getBcc(); + } + + /** + * Set the subject of this message. + * + * @param $subject + * @return $this + */ + public function setSubject($subject) { + $this->swiftMessage->setSubject($subject); + return $this; + } + + /** + * Get the from subject of this message. + * + * @return string + */ + public function getSubject() { + return $this->swiftMessage->getSubject(); + } + + /** + * Set the plain-text body of this message. + * + * @param string $body + * @return $this + */ + public function setPlainBody($body) { + $this->swiftMessage->setBody($body); + return $this; + } + + /** + * Get the plain body of this message. + * + * @return string + */ + public function getPlainBody() { + return $this->swiftMessage->getBody(); + } + + /** + * Set the HTML body of this message. Consider also sending a plain-text body instead of only an HTML one. + * + * @param string $body + * @return $this + */ + public function setHtmlBody($body) { + $this->swiftMessage->addPart($body, 'text/html'); + return $this; + } + + /** + * Get's the underlying SwiftMessage + * @return Swift_Message + */ + public function getSwiftMessage() { + return $this->swiftMessage; + } +} diff --git a/lib/private/mail/util.php b/lib/private/mail/util.php new file mode 100644 index 00000000000..b301e79d492 --- /dev/null +++ b/lib/private/mail/util.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright (c) 2014-2015 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Mail; + +/** + * Class Util + * + * @package OC\Mail + */ +class Util { + /** + * Checks if an e-mail address is valid + * + * @param string $email Email address to be validated + * @return bool True if the mail address is valid, false otherwise + */ + public static function validateMailAddress($email) { + return \Swift_Validate::email(self::convertEmail($email)); + } + + /** + * SwiftMailer does currently not work with IDN domains, this function therefore converts the domains + * + * FIXME: Remove this once SwiftMailer supports IDN + * + * @param string $email + * @return string Converted mail address if `idn_to_ascii` exists + */ + protected static function convertEmail($email) { + if (!function_exists('idn_to_ascii') || strpos($email, '@') === false) { + return $email; + } + + list($name, $domain) = explode('@', $email, 2); + $domain = idn_to_ascii($domain); + return $name.'@'.$domain; + } + +} |