Completed
Push — master ( 22dadb...55e860 )
by Roberto
06:45 queued 03:03
created

Mail   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 298
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 31
lcom 1
cbo 3
dl 0
loc 298
ccs 0
cts 193
cp 0
rs 9.8
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 18 2
A loadService() 0 13 1
A setTemplate() 0 6 2
A loadDocuments() 0 13 3
D getXmlData() 0 69 15
B renderTemplate() 0 34 1
A setAddresses() 0 7 2
B send() 0 24 4
A sendMail() 0 14 1
1
<?php
2
3
namespace NFePHP\Mail;
4
5
/**
6
 * Class for sending emails related to SPED services
7
 *
8
 * @category  NFePHP
9
 * @package   NFePHP\Mail\Mail
10
 * @copyright NFePHP Copyright (c) 2016
11
 * @license   http://www.gnu.org/licenses/lgpl.txt LGPLv3+
12
 * @license   https://opensource.org/licenses/MIT MIT
13
 * @license   http://www.gnu.org/licenses/gpl.txt GPLv3+
14
 * @author    Roberto L. Machado <linux.rlm at gmail dot com>
15
 * @link      http://github.com/nfephp-org/sped-mail for the canonical source repository
16
 */
17
18
use stdClass;
19
use DOMDocument;
20
use DateTime;
21
use InvalidArgumentException;
22
use RuntimeException;
23
use NFePHP\Mail\Base;
24
use PHPMailer;
25
use Html2Text\Html2Text;
26
27
class Mail extends Base
28
{
29
    /**
30
     * config
31
     * @var stdClass
32
     */
33
    protected $config;
34
35
    /**
36
     * Html Body mail message
37
     * @var string
38
     */
39
    protected $body;
40
    /**
41
     * Subject for email
42
     * @var string
43
     */
44
    protected $subject;
45
46
    /**
47
     * Xml content
48
     * @var string
49
     */
50
    protected $xml;
51
    /**
52
     * PDF content
53
     * @var string
54
     */
55
    protected $pdf;
56
    
57
    /**
58
     * Constructor
59
     * @param \stdClass $config
60
     */
61
    public function __construct(stdClass $config, PHPMailer $mailer = null)
62
    {
63
        $this->mail = $mailer;
64
        if (is_null($mailer)) {
65
            $this->mail = new PHPMailer();
66
        }
67
        $this->config = $config;
68
        $this->loadService($config);
69
        $this->fields = new stdClass();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \stdClass() of type object<stdClass> is incompatible with the declared type object<NFePHP\Mail\stdClass> of property $fields.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
70
        $this->fields->destinatario = '';
71
        $this->fields->data = '';
72
        $this->fields->numero = '';
73
        $this->fields->valor = 0;
74
        $this->fields->chave = '';
75
        $this->fields->data = '';
76
        $this->fields->correcao = '';
77
        $this->fields->conduso = '';
78
    }
79
    
80
    /**
81
     * Load parameters to PHPMailer class
82
     * @param stdClass $config
83
     */
84
    protected function loadService(stdClass $config)
85
    {
86
        $this->mail->CharSet = 'UTF-8';
87
        $this->mail->isSMTP();
88
        $this->mail->Host = $config->host;
89
        $this->mail->SMTPAuth = true;
90
        $this->mail->Username = $config->user;
91
        $this->mail->Password = $config->password;
92
        $this->mail->SMTPSecure = $config->secure;
93
        $this->mail->Port = $config->port;
94
        $this->mail->setFrom($config->from, $config->fantasy);
95
        $this->mail->addReplyTo($config->replyTo, $config->replyName);
96
    }
97
    
98
    /**
99
     * Sets a template for body mail
100
     * If no template is passed, it will be used a standard template
101
     * see Base::class
102
     * @param string $htmlTemplate
103
     */
104
    public function setTemplate($htmlTemplate)
105
    {
106
        if ($htmlTemplate != '') {
107
            $this->template = $htmlTemplate;
108
        }
109
    }
110
    
111
    /**
112
     * Load the documents to send
113
     * XML document is required, but PDF is not
114
     * @param string $xml content or path NFe, CTe or CCe in XML
115
     * @param string $pdf content or path document from NFe, CTe or CCe
116
     */
117
    public function loadDocuments($xml, $pdf = '')
118
    {
119
        $this->xml = $xml;
120
        $this->pdf = $pdf;
121
        if (is_file($xml)) {
122
            $this->xml = file_get_contents($xml);
123
        }
124
        if (is_file($pdf)) {
125
            $this->pdf = file_get_contents($pdf);
126
        }
127
        //get xml data
128
        $this->getXmlData($this->xml);
129
    }
130
    
131
    /**
132
     * Search xml for data
133
     * @param string $xml
134
     * @throws InvalidArgumentException
135
     */
136
    protected function getXmlData($xml)
137
    {
138
        $dom = new DOMDocument('1.0', 'UTF-8');
139
        $dom->preserveWhiteSpace = false;
140
        $dom->loadXML($xml);
141
        $root = $dom->documentElement;
142
        $name = $root->tagName;
143
        switch ($name) {
144
            case 'nfeProc':
145
            case 'NFe':
146
                $type = 'NFe';
147
                $this->fields->destinatario = $dom->getElementsByTagName('dest')->item(0)
148
                    ->getElementsByTagName('xNome')->item(0)->nodeValue;
149
                $this->fields->data = $dom->getElementsByTagName('ide')->item(0)
150
                    ->getElementsByTagName('dhEmi')->item(0)->nodeValue;
151
                $this->fields->numero = $dom->getElementsByTagName('ide')->item(0)
152
                     ->getElementsByTagName('nNF')->item(0)->nodeValue;
153
                $this->fields->valor = $dom->getElementsByTagName('vNF')->item(0)->nodeValue;
154
                $this->subject = "NFe n. ".$this->fields->numero." - ".$this->config->fantasy;
155
                break;
156
            case 'cteProc':
157
            case 'CTe':
158
                $type = 'CTe';
159
                $this->fields->destinatario = $dom->getElementsByTagName('dest')->item(0)
160
                    ->getElementsByTagName('xNome')->item(0)->nodeValue;
161
                $this->fields->data = $dom->getElementsByTagName('ide')->item(0)
162
                    ->getElementsByTagName('dhEmi')->item(0)->nodeValue;
163
                $this->fields->numero = $dom->getElementsByTagName('ide')->item(0)
164
                    ->getElementsByTagName('nCT')->item(0)->nodeValue;
165
                $this->fields->valor = $dom->getElementsByTagName('vRec')->item(0)->nodeValue;
166
                $this->subject = "CTe n. ".$this->fields->numero." - ".$this->config->fantasy;
167
                break;
168
            case 'procEventoNFe':
169
            case 'procEventoCTe':
170
                $type = 'CCe';
171
                $this->fields->chave = $dom->getElementsByTagName('chNFe')->item(0)->nodeValue;
172
                $this->fields->data = $dom->getElementsByTagName('dhEvento')->item(0)->nodeValue;
173
                $this->fields->correcao = $dom->getElementsByTagName('xCorrecao')->item(0)->nodeValue;
174
                $this->fields->conduso = $dom->getElementsByTagName('xCondUso')->item(0)->nodeValue;
175
                if (empty($this->fields->chave)) {
176
                    $this->fields->chave = $dom->getElementsByTagName('chCTe')->item(0)->nodeValue;
177
                }
178
                $this->subject = "Carta de Correção ". $this->config->fantasy;
179
                break;
180
            default:
181
                $type = '';
182
        }
183
        //get email adresses from xml, if exists
184
        //may have one address in <dest><email>
185
        $email = !empty($dom->getElementsByTagName('email')->item(0)->nodeValue) ?
186
            $dom->getElementsByTagName('email')->item(0)->nodeValue : '';
187
        if (! empty($email)) {
188
            $this->addresses[] = $email;
189
        }
190
        //may have others in <obsCont xCampo="email"><xTexto>[email protected]</xTexto>
191
        $obs = $dom->getElementsByTagName('obsCont');
192
        foreach ($obs as $ob) {
193
            if (strtoupper($ob->getAttribute('xCampo')) === 'EMAIL') {
194
                $this->addresses[] = $ob->getElementsByTagName('xTexto')->item(0)->nodeValue;
195
            }
196
        }
197
        //xml may be a NFe or a CTe or a CCe nothing else
198
        if ($type != 'NFe' && $type != 'CTe' && $type != 'CCe') {
199
            $msg = "Você deve passar apenas uma NFe ou um CTe ou um CCe. "
200
                    . "Esse documento não foi reconhecido.";
201
            throw new InvalidArgumentException($msg);
202
        }
203
        $this->type = $type;
204
    }
205
    
206
    /**
207
     * Render a template with valid data
208
     * @param string $template
209
     * @param string $destinatario
210
     * @param string $data
211
     * @param string $numero
212
     * @param string $valor
213
     * @param string $chave
214
     * @param string $correcao
215
     * @param string $conduso
216
     * @return string
217
     */
218
    protected function renderTemplate(
219
        $template,
220
        $destinatario = '',
221
        $data = '',
222
        $numero = '',
223
        $valor = 0,
224
        $chave = '',
225
        $correcao = '',
226
        $conduso = ''
227
    ) {
228
        $dt = new \DateTime(str_replace('T', ' ', $data));
229
        $search = array(
230
            '{destinatario}',
231
            '{data}',
232
            '{numero}',
233
            '{valor}',
234
            '{emitente}',
235
            '{chave}',
236
            '{correcao}',
237
            '{conduso}'
238
        );
239
        $replace = array(
240
          $destinatario,
241
          $dt->format('d/m/Y'),
242
          $numero,
243
          number_format($valor, 2, ',', '.'),
244
          $this->config->fantasy,
245
          $chave,
246
          $correcao,
247
          $conduso
248
        );
249
        $template = str_replace($search, $replace, $template);
250
        return $template;
251
    }
252
    
253
    /**
254
     * Set all addresses including those that exists in the xml document
255
     * Send email only to listed addresses ignoring all email addresses in xml
256
     * @param array $addresses
257
     */
258
    protected function setAddresses(array $addresses = [])
259
    {
260
        if (!empty($addresses)) {
261
            $this->addresses = $addresses;
262
        }
263
        $this->removeInvalidAdresses();
264
    }
265
    
266
    /**
267
     * Send mail
268
     * If no parameter was passed, only the email address contained in
269
     * the xml will be used
270
     * @param array $addresses
271
     * @return boolean
272
     * @throws RuntimeException
273
     */
274
    public function send(array $addresses = [])
275
    {
276
        $this->setAddresses($addresses);
277
        if (empty($this->addresses)) {
278
            $msg = 'Não foram passados endereços de email validos !!';
279
            throw new RuntimeException($msg);
280
        }
281
        foreach ($this->addresses as $address) {
282
            $this->mail->addAddress($address);
283
        }
284
        $body = $this->render();
285
        $this->mail->isHTML(true);
286
        $this->mail->Subject = $this->subject;
287
        $this->mail->Body = $body;
288
        $this->mail->AltBody = Html2Text::convert($body);
289
        $this->attach();
290
        if (!$this->mail->send()) {
291
            $msg = 'A mensagem não pode ser enviada. Mail Error: ' . $this->mail->ErrorInfo;
292
            throw new RuntimeException($msg);
293
        }
294
        $this->mail->ClearAllRecipients();
295
        $this->mail->ClearAttachments();
296
        return true;
297
    }
298
    
299
    
300
    /**
301
     * Configure and send documents
302
     * @param stdClass $config
303
     * @param type $xml
304
     * @param type $pdf
305
     * @param array $addresses
306
     * @param type $htmltemplate
307
     * @param PHPMailer $mailer
308
     * @return \static
309
     */
310
    public static function sendMail(
311
        stdClass $config,
312
        $xml,
313
        $pdf = '',
314
        array $addresses = [],
315
        $htmltemplate = '',
316
        PHPMailer $mailer = null
317
    ) {
318
        $mail = new static($config, $mailer);
319
        $mail->loadDocuments($xml, $pdf);
320
        $mail->setTemplate($htmltemplate);
321
        $mail->send($addresses);
322
        return $mail;
323
    }
324
}
325