Completed
Push — 5.x ( 4b3980...241dce )
by Lars
05:15
created

Swift_Transport_MailTransport   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 281
Duplicated Lines 11.39 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 69.31%

Importance

Changes 12
Bugs 5 Features 2
Metric Value
c 12
b 5
f 2
dl 32
loc 281
ccs 70
cts 101
cp 0.6931
rs 9.6
wmc 32
lcom 1
cbo 5

12 Methods

Rating   Name   Duplication   Size   Complexity  
A _formatExtraParams() 0 10 4
A __construct() 0 4 1
A isStarted() 0 4 1
A start() 0 3 1
A stop() 0 3 1
A _getReversePath() 18 18 4
A setExtraParams() 0 6 1
A getExtraParams() 0 4 1
F send() 0 99 12
A registerPlugin() 0 4 1
A _throwException() 14 14 3
A mail() 0 9 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 20
    public function __construct(Swift_Events_EventDispatcher $eventDispatcher)
38
    {
39 20
        $this->_eventDispatcher = $eventDispatcher;
40 20
    }
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
     * Set the additional parameters used on the mail() function.
66
     *
67
     * This string is formatted for sprintf() where %s is the sender address.
68
     *
69
     * @param string $params
70
     *
71
     * @return Swift_Transport_MailTransport
72
     */
73 2
    public function setExtraParams($params)
74
    {
75 2
        $this->_extraParams = $params;
76
77 2
        return $this;
78
    }
79
80
    /**
81
     * Get the additional parameters used on the mail() function.
82
     *
83
     * This string is formatted for sprintf() where %s is the sender address.
84
     *
85
     * @return string
86
     */
87
    public function getExtraParams()
88
    {
89
        return $this->_extraParams;
90
    }
91
92
    /**
93
     * Send the given Message.
94
     *
95
     * Recipient/sender data will be retrieved from the Message API.
96
     * The return value is the number of recipients who were accepted for delivery.
97
     *
98
     * @param Swift_Mime_Message $message
99
     * @param string[]           $failedRecipients An array of failures (by-reference)
100
     *
101
     * @return int
102
     *
103
     * @throws Swift_TransportException
104
     */
105 19
    public function send(Swift_Mime_Message $message, &$failedRecipients = null)
106
    {
107 19
        $failedRecipients = (array)$failedRecipients;
108
109 19
        $evt = $this->_eventDispatcher->createSendEvent($this, $message);
110 19
        if ($evt) {
111
112
            $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
113
            if ($evt->bubbleCancelled()) {
114
                return 0;
115
            }
116
        }
117
118
        $count = (
119 19
            count((array)$message->getTo())
120 19
            + count((array)$message->getCc())
121 19
            + count((array)$message->getBcc())
122
        );
123
124
        /*
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...
125
        // TODO: check if we need this check, breaks "Mockery"-Tests
126
        if ($count === 0) {
127
            $this->_throwException(new Swift_TransportException('Cannot send message without a recipient'));
128
        }
129
        */
130
131 19
        $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...
132 19
        $subjectHeader = $message->getHeaders()->get('Subject');
133
134 19
        if (0 === $count) {
135 1
            $this->_throwException(new Swift_TransportException('Cannot send message without a recipient'));
136
        }
137
138 18
        $to = $toHeader ? $toHeader->getFieldBody() : '';
139 18
        $subject = $subjectHeader ? $subjectHeader->getFieldBody() : '';
140
141 18
        $reversePath = $this->_getReversePath($message);
142
143
        // Remove headers that would otherwise be duplicated
144 18
        $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...
145 18
        $message->getHeaders()->remove('Subject');
146
147 18
        $messageStr = $message->toString();
148
149 18
        if ($toHeader) {
150 18
          $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...
151
        }
152 18
        $message->getHeaders()->set($subjectHeader);
153
154
        // Separate headers from body
155 18
        if (false !== $endHeaders = strpos($messageStr, "\r\n\r\n")) {
156 3
            $headers = substr($messageStr, 0, $endHeaders) . "\r\n"; // Keep last EOL
157 3
            $body = substr($messageStr, $endHeaders + 4);
158
        } else {
159 15
            $headers = $messageStr . "\r\n";
160 15
            $body = '';
161
        }
162
163 18
        unset($messageStr);
164
165 18
        if ("\r\n" !== PHP_EOL) {
166
            // Non-windows (not using SMTP)
167 18
            $headers = str_replace("\r\n", PHP_EOL, $headers);
168 18
            $subject = str_replace("\r\n", PHP_EOL, $subject);
169 18
            $body = str_replace("\r\n", PHP_EOL, $body);
170
        } else {
171
            // Windows, using SMTP
172
            $headers = str_replace("\r\n.", "\r\n..", $headers);
173
            $subject = str_replace("\r\n.", "\r\n..", $subject);
174
            $body = str_replace("\r\n.", "\r\n..", $body);
175
        }
176
177 18
        if ($this->mail($to, $subject, $body, $headers, $this->_formatExtraParams($this->_extraParams, $reversePath))) {
178 1
            if ($evt) {
179
                $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
180
                $evt->setFailedRecipients($failedRecipients);
181 1
                $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
182
            }
183
        } else {
184 17
            $failedRecipients = array_merge(
185
                $failedRecipients,
186 17
                array_keys((array)$message->getTo()),
187 17
                array_keys((array)$message->getCc()),
188 17
                array_keys((array)$message->getBcc())
189
            );
190
191 17
            if ($evt) {
192
                $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED);
193
                $evt->setFailedRecipients($failedRecipients);
194
                $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
195
            }
196
197 17
            $count = 0;
198
        }
199
200 18
        $message->generateId();  // Make sure a new Message ID is used
201
202 18
        return $count;
203
    }
204
205
    /**
206
     * Register a plugin.
207
     *
208
     * @param Swift_Events_EventListener $plugin
209
     */
210
    public function registerPlugin(Swift_Events_EventListener $plugin)
211
    {
212
        $this->_eventDispatcher->bindEventListener($plugin);
213
    }
214
215
    /**
216
     * Throw a TransportException, first sending it to any listeners
217
     *
218
     * @param Swift_TransportException $e
219
     *
220
     * @throws Swift_TransportException
221
     */
222 1 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...
223
    {
224 1
        $evt = $this->_eventDispatcher->createTransportExceptionEvent($this, $e);
225 1
        if ($evt) {
226
227
            $this->_eventDispatcher->dispatchEvent($evt, 'exceptionThrown');
228
            if (!$evt->bubbleCancelled()) {
229
                throw $e;
230
            }
231
232
        } else {
233 1
            throw $e;
234
        }
235
    }
236
237
    /**
238
     * Send mail via the mail() function.
239
     *
240
     * This method takes the same arguments as PHP mail().
241
     *
242
     * @param string $to
243
     * @param string $subject
244
     * @param string $body
245
     * @param string $headers
246
     * @param string $extraParams
247
     *
248
     * @return bool
249
     */
250 3
    public function mail($to, $subject, $body, $headers = null, $extraParams = null)
251
    {
252
        /** @noinspection DeprecatedIniOptionsInspection */
253 3
        if (!ini_get('safe_mode')) {
254 3
            return @mail($to, $subject, $body, $headers, $extraParams);
255
        }
256
257
        return @mail($to, $subject, $body, $headers);
258
    }
259
260
    /**
261
     * Determine the best-use reverse path for this message
262
     *
263
     * @param Swift_Mime_Message $message
264
     *
265
     * @return mixed|null|string
266
     */
267 18 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...
268
    {
269 18
        $return = $message->getReturnPath();
270 18
        $sender = $message->getSender();
271 18
        $from = $message->getFrom();
272 18
        $path = null;
273 18
        if (!empty($return)) {
274 3
            $path = $return;
275 15
        } elseif (!empty($sender)) {
276
            $keys = array_keys($sender);
277
            $path = array_shift($keys);
278 15
        } elseif (!empty($from)) {
279
            $keys = array_keys($from);
280
            $path = array_shift($keys);
281
        }
282
283 18
        return $path;
284
    }
285
286
    /**
287
     * Return php mail extra params to use for invoker->mail.
288
     *
289
     * @param $extraParams
290
     * @param $reversePath
291
     *
292
     * @return mixed string|null
293
     */
294 18
    private function _formatExtraParams($extraParams, $reversePath)
295
    {
296 18
        if (strpos($extraParams, '-f%s') !== false) {
297 17
            $extraParams = empty($reversePath)
298 15
                ? str_replace('-f%s', '', $extraParams)
299 17
                : sprintf($extraParams, escapeshellarg($reversePath));
300
        }
301
302 18
        return !empty($extraParams) ? $extraParams : null;
303
    }
304
}
305