Completed
Push — 5.x ( 2b0825...7df5e8 )
by Lars
04:49
created

Swift_Transport_MailTransport::ping()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
rs 10
c 1
b 0
f 1
1
<?php
2
3
/*
4
 * This file is part of SwiftMailer.
5
 * (c) 2004-2009 Chris Corbyn
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
/**
12
 * Sends Messages using the mail() function.
13
 *
14
 * It is advised that users do not use this transport if at all possible
15
 * since a number of plugin features cannot be used in conjunction with this
16
 * transport due to the internal interface in PHP itself.
17
 *
18
 * The level of error reporting with this transport is incredibly weak, again
19
 * due to limitations of PHP's internal mail() function.  You'll get an
20
 * all-or-nothing result from sending.
21
 *
22
 * @author Chris Corbyn
23
 */
24
class Swift_Transport_MailTransport implements Swift_Transport
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
25
{
26
    /** Additional parameters to pass to mail() */
27
    private $_extraParams = '-f%s';
28
29
    /** The event dispatcher from the plugin API */
30
    private $_eventDispatcher;
31
32
    /**
33
     * Create a new MailTransport with the $log.
34
     *
35
     * @param Swift_Events_EventDispatcher $eventDispatcher
36
     */
37 16
    public function __construct(Swift_Events_EventDispatcher $eventDispatcher)
38
    {
39 16
        $this->_eventDispatcher = $eventDispatcher;
40 16
    }
41
42
    /**
43
     * Not used.
44
     */
45
    public function isStarted()
46
    {
47
        return false;
48
    }
49
50
    /**
51
     * Not used.
52
     */
53
    public function start()
54
    {
55
    }
56
57
    /**
58
     * Not used.
59
     */
60
    public function stop()
61
    {
62
    }
63
64
    /**
65
     * Check if this Transport mechanism is alive.
66
     *
67
     * If a Transport mechanism session is no longer functional, the method
68
     * returns FALSE. It is the responsibility of the developer to handle this
69
     * case and restart the Transport mechanism manually.
70
     *
71
     * @example
72
     *
73
     *   if (!$transport->ping()) {
74
     *      $transport->stop();
75
     *      $transport->start();
76
     *   }
77
     *
78
     * The Transport mechanism will be started, if it is not already.
79
     *
80
     * It is undefined if the Transport mechanism attempts to restart as long as
81
     * the return value reflects whether the mechanism is now functional.
82
     *
83
     * @return bool TRUE if the transport is alive
84
     */
85
    public function ping()
86
    {
87
        return true;
88
    }
89
90
    /**
91
     * Set the additional parameters used on the mail() function.
92
     *
93
     * This string is formatted for sprintf() where %s is the sender address.
94
     *
95
     * @param string $params
96
     *
97
     * @return Swift_Transport_MailTransport
98
     */
99 2
    public function setExtraParams($params)
100
    {
101 2
        $this->_extraParams = $params;
102
103 2
        return $this;
104
    }
105
106
    /**
107
     * Get the additional parameters used on the mail() function.
108
     *
109
     * This string is formatted for sprintf() where %s is the sender address.
110
     *
111
     * @return string
112
     */
113
    public function getExtraParams()
114
    {
115
        return $this->_extraParams;
116
    }
117
118
    /**
119
     * Send the given Message.
120
     *
121
     * Recipient/sender data will be retrieved from the Message API.
122
     * The return value is the number of recipients who were accepted for delivery.
123
     *
124
     * @param Swift_Mime_Message $message
125
     * @param string[]           $failedRecipients An array of failures by-reference
126
     *
127
     * @return int
128
     *
129
     * @throws Swift_TransportException
130
     */
131 15
    public function send(Swift_Mime_Message $message, &$failedRecipients = null)
132
    {
133 15
        $failedRecipients = (array)$failedRecipients;
134
135 15
        $evt = $this->_eventDispatcher->createSendEvent($this, $message);
136 15
        if ($evt) {
137
138
            $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
139
            if ($evt->bubbleCancelled()) {
140
                return 0;
141
            }
142
        }
143
144
        $count = (
145 15
            count((array)$message->getTo())
146 15
            + count((array)$message->getCc())
147 15
            + count((array)$message->getBcc())
148
        );
149
150
        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
151
        // TODO: check if we need this check, breaks "Mockery"-Tests
152
        if ($count === 0) {
153
            $this->_throwException(new Swift_TransportException('Cannot send message without a recipient'));
154
        }
155
        */
156
157 15
        $toHeader = $message->getHeaders()->get('To');
0 ignored issues
show
Bug introduced by
The method get does only exist in Swift_Mime_HeaderSet, but not in Swift_Mime_Header.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
158 15
        $subjectHeader = $message->getHeaders()->get('Subject');
159
160 15
        if (!$toHeader) {
161
            $this->_throwException(new Swift_TransportException('Cannot send message without a recipient'));
162
        }
163
164 15
        $to = $toHeader->getFieldBody();
165 15
        $subject = $subjectHeader ? $subjectHeader->getFieldBody() : '';
166
167 15
        $reversePath = $this->_getReversePath($message);
168
169
        // Remove headers that would otherwise be duplicated
170 15
        $message->getHeaders()->remove('To');
0 ignored issues
show
Bug introduced by
The method remove does only exist in Swift_Mime_HeaderSet, but not in Swift_Mime_Header.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
171 15
        $message->getHeaders()->remove('Subject');
172
173 15
        $messageStr = $message->toString();
174
175 15
        $message->getHeaders()->set($toHeader);
0 ignored issues
show
Bug introduced by
The method set does only exist in Swift_Mime_HeaderSet, but not in Swift_Mime_Header.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
176 15
        $message->getHeaders()->set($subjectHeader);
177
178
        // Separate headers from body
179 15
        if (false !== $endHeaders = strpos($messageStr, "\r\n\r\n")) {
180 3
            $headers = substr($messageStr, 0, $endHeaders) . "\r\n"; // Keep last EOL
181 3
            $body = substr($messageStr, $endHeaders + 4);
182
        } else {
183 12
            $headers = $messageStr . "\r\n";
184 12
            $body = '';
185
        }
186
187 15
        unset($messageStr);
188
189 15
        if ("\r\n" != PHP_EOL) {
190
            // Non-windows (not using SMTP)
191 15
            $headers = str_replace("\r\n", PHP_EOL, $headers);
192 15
            $subject = str_replace("\r\n", PHP_EOL, $subject);
193 15
            $body = str_replace("\r\n", PHP_EOL, $body);
194
        } else {
195
            // Windows, using SMTP
196
            $headers = str_replace("\r\n.", "\r\n..", $headers);
197
            $subject = str_replace("\r\n.", "\r\n..", $subject);
198
            $body = str_replace("\r\n.", "\r\n..", $body);
199
        }
200
201 15
        if ($this->mail($to, $subject, $body, $headers, $this->_formatExtraParams($this->_extraParams, $reversePath))) {
202 1
            if ($evt) {
203
                $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
204
                $evt->setFailedRecipients($failedRecipients);
205 1
                $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
206
            }
207
        } else {
208 14
            $failedRecipients = array_merge(
209
                $failedRecipients,
210 14
                array_keys((array)$message->getTo()),
211 14
                array_keys((array)$message->getCc()),
212 14
                array_keys((array)$message->getBcc())
213
            );
214
215 14
            if ($evt) {
216
                $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED);
217
                $evt->setFailedRecipients($failedRecipients);
218
                $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
219
            }
220
221
            // TODO: Why do we do this only on error?
222
            // -> take a look at "AbstractSmtpTransport"
223
            //
224 14
            $message->generateId(); // Make sure a new Message ID is used
225
226 14
            $count = 0;
227
        }
228
229 15
        return $count;
230
    }
231
232
    /**
233
     * Register a plugin.
234
     *
235
     * @param Swift_Events_EventListener $plugin
236
     */
237
    public function registerPlugin(Swift_Events_EventListener $plugin)
238
    {
239
        $this->_eventDispatcher->bindEventListener($plugin);
240
    }
241
242
    /**
243
     * Throw a TransportException, first sending it to any listeners
244
     *
245
     * @param Swift_TransportException $e
246
     *
247
     * @throws Swift_TransportException
248
     */
249 View Code Duplication
    protected function _throwException(Swift_TransportException $e)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
250
    {
251
        $evt = $this->_eventDispatcher->createTransportExceptionEvent($this, $e);
252
        if ($evt) {
253
254
            $this->_eventDispatcher->dispatchEvent($evt, 'exceptionThrown');
255
            if (!$evt->bubbleCancelled()) {
256
                throw $e;
257
            }
258
259
        } else {
260
            throw $e;
261
        }
262
    }
263
264
    /**
265
     * Send mail via the mail() function.
266
     *
267
     * This method takes the same arguments as PHP mail().
268
     *
269
     * @param string $to
270
     * @param string $subject
271
     * @param string $body
272
     * @param string $headers
273
     * @param string $extraParams
274
     *
275
     * @return bool
276
     */
277
    public function mail($to, $subject, $body, $headers = null, $extraParams = null)
278
    {
279
        if (!ini_get('safe_mode')) {
280
            return @mail($to, $subject, $body, $headers, $extraParams);
281
        }
282
283
        return @mail($to, $subject, $body, $headers);
284
    }
285
286
    /**
287
     * Determine the best-use reverse path for this message
288
     *
289
     * @param Swift_Mime_Message $message
290
     *
291
     * @return mixed|null|string
292
     */
293 15 View Code Duplication
    private function _getReversePath(Swift_Mime_Message $message)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
294
    {
295 15
        $return = $message->getReturnPath();
296 15
        $sender = $message->getSender();
297 15
        $from = $message->getFrom();
298 15
        $path = null;
299 15
        if (!empty($return)) {
300 3
            $path = $return;
301 12
        } elseif (!empty($sender)) {
302
            $keys = array_keys($sender);
303
            $path = array_shift($keys);
304 12
        } elseif (!empty($from)) {
305
            $keys = array_keys($from);
306
            $path = array_shift($keys);
307
        }
308
309 15
        return $path;
310
    }
311
312
    /**
313
     * Return php mail extra params to use for invoker->mail.
314
     *
315
     * @param $extraParams
316
     * @param $reversePath
317
     *
318
     * @return mixed string|null
319
     */
320 15
    private function _formatExtraParams($extraParams, $reversePath)
321
    {
322 15
        if (strpos($extraParams, '-f%s') !== false) {
323 14
            $extraParams = empty($reversePath)
324 12
                ? str_replace('-f%s', '', $extraParams)
325 14
                : sprintf($extraParams, escapeshellarg($reversePath));
326
        }
327
328 15
        return !empty($extraParams) ? $extraParams : null;
329
    }
330
}
331