Completed
Push — master ( 73aef9...c8323f )
by Georg
60:20 queued 46:52
created

Mailer::createAttachmentFromPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Lukas Reschke <[email protected]>
6
 *
7
 * @license AGPL-3.0
8
 *
9
 * This code is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License, version 3,
11
 * as published by the Free Software Foundation.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License, version 3,
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
20
 *
21
 */
22
23
namespace OC\Mail;
24
25
use OCP\Defaults;
26
use OCP\IConfig;
27
use OCP\IL10N;
28
use OCP\IURLGenerator;
29
use OCP\Mail\IAttachment;
30
use OCP\Mail\IEMailTemplate;
31
use OCP\Mail\IMailer;
32
use OCP\ILogger;
33
use OCP\Mail\IMessage;
34
35
/**
36
 * Class Mailer provides some basic functions to create a mail message that can be used in combination with
37
 * \OC\Mail\Message.
38
 *
39
 * Example usage:
40
 *
41
 * 	$mailer = \OC::$server->getMailer();
42
 * 	$message = $mailer->createMessage();
43
 * 	$message->setSubject('Your Subject');
44
 * 	$message->setFrom(array('[email protected]' => 'ownCloud Notifier');
45
 * 	$message->setTo(array('[email protected]' => 'Recipient');
46
 * 	$message->setBody('The message text');
47
 * 	$mailer->send($message);
48
 *
49
 * This message can then be passed to send() of \OC\Mail\Mailer
50
 *
51
 * @package OC\Mail
52
 */
53
class Mailer implements IMailer {
54
	/** @var \Swift_SmtpTransport|\Swift_SendmailTransport|\Swift_MailTransport Cached transport */
55
	private $instance = null;
56
	/** @var IConfig */
57
	private $config;
58
	/** @var ILogger */
59
	private $logger;
60
	/** @var Defaults */
61
	private $defaults;
62
	/** @var IURLGenerator */
63
	private $urlGenerator;
64
	/** @var IL10N */
65
	private $l10n;
66
67
	/**
68
	 * @param IConfig $config
69
	 * @param ILogger $logger
70
	 * @param Defaults $defaults
71
	 * @param IURLGenerator $urlGenerator
72
	 * @param IL10N $l10n
73
	 */
74 View Code Duplication
	public function __construct(IConfig $config,
75
						 ILogger $logger,
76
						 Defaults $defaults,
77
						 IURLGenerator $urlGenerator,
78
						 IL10N $l10n) {
79
		$this->config = $config;
80
		$this->logger = $logger;
81
		$this->defaults = $defaults;
82
		$this->urlGenerator = $urlGenerator;
83
		$this->l10n = $l10n;
84
	}
85
86
	/**
87
	 * Creates a new message object that can be passed to send()
88
	 *
89
	 * @return IMessage
90
	 */
91
	public function createMessage() {
92
		return new Message(new \Swift_Message());
93
	}
94
95
	/**
96
	 * @param string|null $data
97
	 * @param string|null $filename
98
	 * @param string|null $contentType
99
	 * @return IAttachment
100
	 * @since 13.0.0
101
	 */
102
	public function createAttachment($data = null, $filename = null, $contentType = null) {
103
		return new Attachment(\Swift_Attachment::newInstance($data, $filename, $contentType));
104
	}
105
106
	/**
107
	 * @param string $path
108
	 * @param string|null $contentType
109
	 * @return IAttachment
110
	 * @since 13.0.0
111
	 */
112
	public function createAttachmentFromPath($path, $contentType = null) {
113
		return new Attachment(\Swift_Attachment::fromPath($path, $contentType));
114
	}
115
116
	/**
117
	 * Creates a new email template object
118
	 *
119
	 * @param string $emailId
120
	 * @param array $data
121
	 * @return IEMailTemplate
122
	 * @since 12.0.0
123
	 */
124
	public function createEMailTemplate($emailId, array $data = []) {
125
		$class = $this->config->getSystemValue('mail_template_class', '');
126
127
		if ($class !== '' && class_exists($class) && is_a($class, EMailTemplate::class, true)) {
128
			return new $class(
129
				$this->defaults,
130
				$this->urlGenerator,
131
				$this->l10n,
132
				$emailId,
133
				$data
134
			);
135
		}
136
137
		return new EMailTemplate(
138
			$this->defaults,
139
			$this->urlGenerator,
140
			$this->l10n,
141
			$emailId,
142
			$data
143
		);
144
	}
145
146
	/**
147
	 * Send the specified message. Also sets the from address to the value defined in config.php
148
	 * if no-one has been passed.
149
	 *
150
	 * @param IMessage|Message $message Message to send
151
	 * @return string[] Array with failed recipients. Be aware that this depends on the used mail backend and
152
	 * therefore should be considered
153
	 * @throws \Exception In case it was not possible to send the message. (for example if an invalid mail address
154
	 * has been supplied.)
155
	 */
156
	public function send(IMessage $message) {
157
		$debugMode = $this->config->getSystemValue('mail_smtpdebug', false);
158
159
		if (empty($message->getFrom())) {
160
			$message->setFrom([\OCP\Util::getDefaultEmailAddress($this->defaults->getName()) => $this->defaults->getName()]);
161
		}
162
163
		$failedRecipients = [];
164
165
		$mailer = $this->getInstance();
166
167
		// Enable logger if debug mode is enabled
168
		if($debugMode) {
169
			$mailLogger = new \Swift_Plugins_Loggers_ArrayLogger();
170
			$mailer->registerPlugin(new \Swift_Plugins_LoggerPlugin($mailLogger));
171
		}
172
173
		$mailer->send($message->getSwiftMessage(), $failedRecipients);
174
175
		// Debugging logging
176
		$logMessage = sprintf('Sent mail to "%s" with subject "%s"', print_r($message->getTo(), true), $message->getSubject());
177
		$this->logger->debug($logMessage, ['app' => 'core']);
178
		if($debugMode && isset($mailLogger)) {
179
			$this->logger->debug($mailLogger->dump(), ['app' => 'core']);
180
		}
181
182
		return $failedRecipients;
183
	}
184
185
	/**
186
	 * Checks if an e-mail address is valid
187
	 *
188
	 * @param string $email Email address to be validated
189
	 * @return bool True if the mail address is valid, false otherwise
190
	 */
191
	public function validateMailAddress($email) {
192
		return \Swift_Validate::email($this->convertEmail($email));
193
	}
194
195
	/**
196
	 * SwiftMailer does currently not work with IDN domains, this function therefore converts the domains
197
	 *
198
	 * FIXME: Remove this once SwiftMailer supports IDN
199
	 *
200
	 * @param string $email
201
	 * @return string Converted mail address if `idn_to_ascii` exists
202
	 */
203
	protected function convertEmail($email) {
204
		if (!function_exists('idn_to_ascii') || strpos($email, '@') === false) {
205
			return $email;
206
		}
207
208
		list($name, $domain) = explode('@', $email, 2);
209
		$domain = idn_to_ascii($domain, 0,INTL_IDNA_VARIANT_UTS46);
210
		return $name.'@'.$domain;
211
	}
212
213
	/**
214
	 * Returns whatever transport is configured within the config
215
	 *
216
	 * @return \Swift_SmtpTransport|\Swift_SendmailTransport|\Swift_MailTransport
217
	 */
218
	protected function getInstance() {
219
		if (!is_null($this->instance)) {
220
			return $this->instance;
221
		}
222
223
		switch ($this->config->getSystemValue('mail_smtpmode', 'php')) {
224
			case 'smtp':
225
				$this->instance = $this->getSmtpInstance();
226
				break;
227
			case 'sendmail':
228
				// FIXME: Move into the return statement but requires proper testing
229
				//       for SMTP and mail as well. Thus not really doable for a
230
				//       minor release.
231
				$this->instance = \Swift_Mailer::newInstance($this->getSendMailInstance());
232
				break;
233
			default:
234
				$this->instance = $this->getMailInstance();
235
				break;
236
		}
237
238
		return $this->instance;
239
	}
240
241
	/**
242
	 * Returns the SMTP transport
243
	 *
244
	 * @return \Swift_SmtpTransport
245
	 */
246
	protected function getSmtpInstance() {
247
		$transport = \Swift_SmtpTransport::newInstance();
248
		$transport->setTimeout($this->config->getSystemValue('mail_smtptimeout', 10));
249
		$transport->setHost($this->config->getSystemValue('mail_smtphost', '127.0.0.1'));
250
		$transport->setPort($this->config->getSystemValue('mail_smtpport', 25));
251
		if ($this->config->getSystemValue('mail_smtpauth', false)) {
252
			$transport->setUsername($this->config->getSystemValue('mail_smtpname', ''));
253
			$transport->setPassword($this->config->getSystemValue('mail_smtppassword', ''));
254
			$transport->setAuthMode($this->config->getSystemValue('mail_smtpauthtype', 'LOGIN'));
255
		}
256
		$smtpSecurity = $this->config->getSystemValue('mail_smtpsecure', '');
257
		if (!empty($smtpSecurity)) {
258
			$transport->setEncryption($smtpSecurity);
259
		}
260
		$transport->start();
261
		return $transport;
262
	}
263
264
	/**
265
	 * Returns the sendmail transport
266
	 *
267
	 * @return \Swift_SendmailTransport
268
	 */
269
	protected function getSendMailInstance() {
270
		switch ($this->config->getSystemValue('mail_smtpmode', 'php')) {
271
			case 'qmail':
272
				$binaryPath = '/var/qmail/bin/sendmail';
273
				break;
274
			default:
275
				$binaryPath = '/usr/sbin/sendmail';
276
				break;
277
		}
278
279
		return \Swift_SendmailTransport::newInstance($binaryPath . ' -bs');
280
	}
281
282
	/**
283
	 * Returns the mail transport
284
	 *
285
	 * @return \Swift_MailTransport
286
	 */
287
	protected function getMailInstance() {
288
		return \Swift_MailTransport::newInstance();
289
	}
290
291
}
292