mailer.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. <?php
  2. /**
  3. * @author Lukas Reschke <lukas@owncloud.com>
  4. *
  5. * @copyright Copyright (c) 2015, ownCloud, Inc.
  6. * @license AGPL-3.0
  7. *
  8. * This code is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License, version 3,
  10. * as published by the Free Software Foundation.
  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, version 3,
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>
  19. *
  20. */
  21. namespace OC\Mail;
  22. use OCP\IConfig;
  23. use OCP\Mail\IMailer;
  24. use OCP\ILogger;
  25. /**
  26. * Class Mailer provides some basic functions to create a mail message that can be used in combination with
  27. * \OC\Mail\Message.
  28. *
  29. * Example usage:
  30. *
  31. * $mailer = \OC::$server->getMailer();
  32. * $message = $mailer->createMessage();
  33. * $message->setSubject('Your Subject');
  34. * $message->setFrom(array('cloud@domain.org' => 'ownCloud Notifier');
  35. * $message->setTo(array('recipient@domain.org' => 'Recipient');
  36. * $message->setBody('The message text');
  37. * $mailer->send($message);
  38. *
  39. * This message can then be passed to send() of \OC\Mail\Mailer
  40. *
  41. * @package OC\Mail
  42. */
  43. class Mailer implements IMailer {
  44. /** @var \Swift_SmtpTransport|\Swift_SendmailTransport|\Swift_MailTransport Cached transport */
  45. private $instance = null;
  46. /** @var IConfig */
  47. private $config;
  48. /** @var ILogger */
  49. private $logger;
  50. /** @var \OC_Defaults */
  51. private $defaults;
  52. /**
  53. * @param IConfig $config
  54. * @param ILogger $logger
  55. * @param \OC_Defaults $defaults
  56. */
  57. function __construct(IConfig $config,
  58. ILogger $logger,
  59. \OC_Defaults $defaults) {
  60. $this->config = $config;
  61. $this->logger = $logger;
  62. $this->defaults = $defaults;
  63. }
  64. /**
  65. * Creates a new message object that can be passed to send()
  66. *
  67. * @return Message
  68. */
  69. public function createMessage() {
  70. return new Message(new \Swift_Message());
  71. }
  72. /**
  73. * Send the specified message. Also sets the from address to the value defined in config.php
  74. * if no-one has been passed.
  75. *
  76. * @param Message $message Message to send
  77. * @return string[] Array with failed recipients. Be aware that this depends on the used mail backend and
  78. * therefore should be considered
  79. * @throws \Exception In case it was not possible to send the message. (for example if an invalid mail address
  80. * has been supplied.)
  81. */
  82. public function send(Message $message) {
  83. $debugMode = $this->config->getSystemValue('mail_smtpdebug', false);
  84. if (sizeof($message->getFrom()) === 0) {
  85. $message->setFrom([\OCP\Util::getDefaultEmailAddress($this->defaults->getName())]);
  86. }
  87. $failedRecipients = [];
  88. $mailer = $this->getInstance();
  89. // Enable logger if debug mode is enabled
  90. if($debugMode) {
  91. $mailLogger = new \Swift_Plugins_Loggers_ArrayLogger();
  92. $mailer->registerPlugin(new \Swift_Plugins_LoggerPlugin($mailLogger));
  93. }
  94. $mailer->send($message->getSwiftMessage(), $failedRecipients);
  95. // Debugging logging
  96. $logMessage = sprintf('Sent mail to "%s" with subject "%s"', print_r($message->getTo(), true), $message->getSubject());
  97. $this->logger->debug($logMessage, ['app' => 'core']);
  98. if($debugMode && isset($mailLogger)) {
  99. $this->logger->debug($mailLogger->dump(), ['app' => 'core']);
  100. }
  101. return $failedRecipients;
  102. }
  103. /**
  104. * Checks if an e-mail address is valid
  105. *
  106. * @param string $email Email address to be validated
  107. * @return bool True if the mail address is valid, false otherwise
  108. */
  109. public function validateMailAddress($email) {
  110. return \Swift_Validate::email($this->convertEmail($email));
  111. }
  112. /**
  113. * SwiftMailer does currently not work with IDN domains, this function therefore converts the domains
  114. *
  115. * FIXME: Remove this once SwiftMailer supports IDN
  116. *
  117. * @param string $email
  118. * @return string Converted mail address if `idn_to_ascii` exists
  119. */
  120. protected function convertEmail($email) {
  121. if (!function_exists('idn_to_ascii') || strpos($email, '@') === false) {
  122. return $email;
  123. }
  124. list($name, $domain) = explode('@', $email, 2);
  125. $domain = idn_to_ascii($domain);
  126. return $name.'@'.$domain;
  127. }
  128. /**
  129. * Returns whatever transport is configured within the config
  130. *
  131. * @return \Swift_SmtpTransport|\Swift_SendmailTransport|\Swift_MailTransport
  132. */
  133. protected function getInstance() {
  134. if (!is_null($this->instance)) {
  135. return $this->instance;
  136. }
  137. switch ($this->config->getSystemValue('mail_smtpmode', 'php')) {
  138. case 'smtp':
  139. $this->instance = $this->getSMTPInstance();
  140. break;
  141. case 'sendmail':
  142. $this->instance = $this->getSendMailInstance();
  143. break;
  144. default:
  145. $this->instance = $this->getMailInstance();
  146. break;
  147. }
  148. return $this->instance;
  149. }
  150. /**
  151. * Returns the SMTP transport
  152. *
  153. * @return \Swift_SmtpTransport
  154. */
  155. protected function getSmtpInstance() {
  156. $transport = \Swift_SmtpTransport::newInstance();
  157. $transport->setTimeout($this->config->getSystemValue('mail_smtptimeout', 10));
  158. $transport->setHost($this->config->getSystemValue('mail_smtphost', '127.0.0.1'));
  159. $transport->setPort($this->config->getSystemValue('mail_smtpport', 25));
  160. if ($this->config->getSystemValue('mail_smtpauth', false)) {
  161. $transport->setUsername($this->config->getSystemValue('mail_smtpname', ''));
  162. $transport->setPassword($this->config->getSystemValue('mail_smtppassword', ''));
  163. $transport->setAuthMode($this->config->getSystemValue('mail_smtpauthtype', 'LOGIN'));
  164. }
  165. $smtpSecurity = $this->config->getSystemValue('mail_smtpsecure', '');
  166. if (!empty($smtpSecurity)) {
  167. $transport->setEncryption($smtpSecurity);
  168. }
  169. $transport->start();
  170. return $transport;
  171. }
  172. /**
  173. * Returns the sendmail transport
  174. *
  175. * @return \Swift_SendmailTransport
  176. */
  177. protected function getSendMailInstance() {
  178. switch ($this->config->getSystemValue('mail_smtpmode', 'sendmail')) {
  179. case 'qmail':
  180. $binaryPath = '/var/qmail/bin/sendmail';
  181. break;
  182. default:
  183. $binaryPath = '/usr/sbin/sendmail';
  184. break;
  185. }
  186. return \Swift_SendmailTransport::newInstance($binaryPath . ' -bs');
  187. }
  188. /**
  189. * Returns the mail transport
  190. *
  191. * @return \Swift_MailTransport
  192. */
  193. protected function getMailInstance() {
  194. return \Swift_MailTransport::newInstance();
  195. }
  196. }