1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace NFePHP\Mail; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Class for sending emails related to SPED services |
7
|
|
|
* |
8
|
|
|
* @category library |
9
|
|
|
* @package NFePHP\Mail\Mail |
10
|
|
|
* @copyright NFePHP Copyright (c) 2008-2019 |
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 NFePHP\Mail\Base; |
19
|
|
|
use PHPMailer\PHPMailer\PHPMailer; |
20
|
|
|
use PHPMailer\PHPMailer\SMTP; |
21
|
|
|
use Html2Text\Html2Text; |
22
|
|
|
use NFePHP\Common\Certificate; |
23
|
|
|
|
24
|
|
|
class Mail extends Base |
25
|
|
|
{ |
26
|
|
|
/** |
27
|
|
|
* Html Body mail message |
28
|
|
|
* @var string |
29
|
|
|
*/ |
30
|
|
|
public $body; |
31
|
|
|
/** |
32
|
|
|
* Subject for email |
33
|
|
|
* @var string |
34
|
|
|
*/ |
35
|
|
|
public $subject; |
36
|
|
|
/** |
37
|
|
|
* Certificate class |
38
|
|
|
* @var Certificate |
39
|
|
|
*/ |
40
|
|
|
protected $certificate; |
41
|
|
|
|
42
|
|
|
protected $sign = false; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Constructor |
46
|
|
|
* @param \stdClass $config |
47
|
|
|
* @param null|\PHPMailer\PHPMailer\PHPMailer $mailer |
48
|
|
|
*/ |
49
|
|
|
public function __construct(\stdClass $config, PHPMailer $mailer = null) |
50
|
|
|
{ |
51
|
|
|
$this->mail = $mailer; |
|
|
|
|
52
|
|
|
if (is_null($mailer)) { |
53
|
|
|
$this->mail = new PHPMailer(); |
|
|
|
|
54
|
|
|
} |
55
|
|
|
$this->config = $config; |
56
|
|
|
$this->loadService($config); |
57
|
|
|
$this->fields = new \stdClass(); |
58
|
|
|
$this->fields->destinatario = ''; |
59
|
|
|
$this->fields->data = ''; |
60
|
|
|
$this->fields->numero = ''; |
61
|
|
|
$this->fields->valor = 0; |
62
|
|
|
$this->fields->chave = ''; |
63
|
|
|
$this->fields->data = ''; |
64
|
|
|
$this->fields->correcao = ''; |
65
|
|
|
$this->fields->conduso = ''; |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Load parameters to PHPMailer class |
70
|
|
|
* @param \stdClass $config |
71
|
|
|
*/ |
72
|
|
|
protected function loadService(\stdClass $config) |
73
|
|
|
{ |
74
|
|
|
$this->mail->CharSet = 'UTF-8'; |
75
|
|
|
$this->mail->isSMTP(); |
76
|
|
|
$this->mail->Host = $config->host; |
77
|
|
|
$this->mail->Timeout = !empty($config->timeout) |
78
|
|
|
? $config->timeout |
79
|
|
|
: 300; |
80
|
|
|
$this->mail->SMTPAuth = !empty($config->smtpauth) |
81
|
|
|
? $config->smtpauth |
82
|
|
|
: false; |
83
|
|
|
$this->mail->AuthType = !empty($config->authtype) |
84
|
|
|
? $config->authtype |
85
|
|
|
: ''; |
86
|
|
|
$this->mail->SMTPSecure = !empty($config->secure) |
87
|
|
|
? $config->secure |
88
|
|
|
: ''; |
89
|
|
|
$this->mail->Port = !empty($config->port) |
90
|
|
|
? $config->port |
91
|
|
|
: 25; |
92
|
|
|
if (!empty($config->user) && !empty($config->password)) { |
93
|
|
|
$this->mail->SMTPAuth = true; |
94
|
|
|
$this->mail->Username = $config->user; |
95
|
|
|
$this->mail->Password = $config->password; |
96
|
|
|
} |
97
|
|
|
if (!empty($config->smtpoptions) && is_array($config->smtpoptions)) { |
98
|
|
|
$this->mail->SMTPOptions = $config->smtpoptions; |
99
|
|
|
} |
100
|
|
|
$this->mail->SMTPDebug = isset($config->smtpdebug) |
101
|
|
|
? $config->smtpdebug |
102
|
|
|
: 0; |
103
|
|
|
$this->mail->Debugoutput = !empty($config->debugoutput) |
104
|
|
|
? $config->debugoutput |
105
|
|
|
: ''; |
106
|
|
|
$this->mail->setFrom($config->from, $config->fantasy); |
107
|
|
|
$this->mail->addReplyTo($config->replyTo, $config->replyName); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Sets a template for body mail |
112
|
|
|
* If no template is passed, it will be used a standard template |
113
|
|
|
* see Base::class |
114
|
|
|
* @param string $htmlTemplate |
115
|
|
|
*/ |
116
|
|
|
public function loadTemplate($htmlTemplate = '') |
117
|
|
|
{ |
118
|
|
|
if ($htmlTemplate != '') { |
119
|
|
|
$this->template = $htmlTemplate; |
120
|
|
|
} |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Enable S/MIME signed mail |
125
|
|
|
* @param null|string $pfx |
126
|
|
|
* @param null|string $password |
127
|
|
|
* @return void |
128
|
|
|
*/ |
129
|
|
|
public function enableSignature($pfx = null, $password = null) |
130
|
|
|
{ |
131
|
|
|
if (empty($pfx) || empty($password)) { |
132
|
|
|
$this->sign = false; |
133
|
|
|
return; |
134
|
|
|
} |
135
|
|
|
$this->certificate = Certificate::readPfx($pfx, $password); |
136
|
|
|
$this->sign = true; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* Load the documents to send |
141
|
|
|
* XML document is required, but PDF is not |
142
|
|
|
* @param string $xml content or path NFe, CTe or CCe in XML |
143
|
|
|
* @param string $pdf content or path document from NFe, CTe or CCe |
144
|
|
|
*/ |
145
|
|
|
public function loadDocuments($xml, $pdf = '') |
146
|
|
|
{ |
147
|
|
|
$this->xml = trim($xml); |
148
|
|
|
$this->pdf = trim($pdf); |
149
|
|
|
if ($this->isFile($this->xml)) { |
150
|
|
|
$this->xml = file_get_contents($this->xml); |
151
|
|
|
} |
152
|
|
|
if ($this->isFile($this->pdf)) { |
153
|
|
|
$this->pdf = file_get_contents($this->pdf); |
154
|
|
|
} |
155
|
|
|
//get xml data |
156
|
|
|
$this->getXmlData($this->xml); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Checks if given data is file |
161
|
|
|
* @param string $value |
162
|
|
|
* @return boolean |
163
|
|
|
*/ |
164
|
|
|
private function isFile($value) |
165
|
|
|
{ |
166
|
|
|
//se a string for maior que 500bytes, provavelmente é o conteudo |
167
|
|
|
//de um xml ou de um PDF então verificar |
168
|
|
|
if (strlen($value) > 500 |
169
|
|
|
&& (substr($value, 0, 1) == '<' || substr($value, 0, 5) == "%PDF-") |
170
|
|
|
) { |
171
|
|
|
return false; |
172
|
|
|
} |
173
|
|
|
//caso contrario pode ser um path muito longo !! |
174
|
|
|
$value = strval(str_replace("\0", "", $value)); |
175
|
|
|
return is_file($value); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Send mail |
180
|
|
|
* If no parameter was passed, only the email address contained in |
181
|
|
|
* the xml will be used |
182
|
|
|
* @param array $addresses |
183
|
|
|
* @return boolean |
184
|
|
|
* @throws \RuntimeException |
185
|
|
|
*/ |
186
|
|
|
public function send(array $addresses = [], $include = true) |
187
|
|
|
{ |
188
|
|
|
$this->setAddresses($addresses, $include); |
189
|
|
|
if (empty($this->addresses)) { |
190
|
|
|
$msg = 'Não foram passados endereços de email validos !!'; |
191
|
|
|
throw new \RuntimeException($msg); |
192
|
|
|
} |
193
|
|
|
foreach ($this->addresses as $address) { |
194
|
|
|
$this->mail->addAddress($address); |
195
|
|
|
} |
196
|
|
|
$body = $this->render(); |
197
|
|
|
$this->mail->isHTML(true); |
198
|
|
|
$this->mail->Subject = $this->subject; |
199
|
|
|
$this->mail->Body = $body; |
200
|
|
|
$this->mail->AltBody = Html2Text::convert($body); |
201
|
|
|
$this->attach(); |
202
|
|
|
if ($this->sign) { |
203
|
|
|
$dir = sys_get_temp_dir(); |
204
|
|
|
$cert = tempnam($dir, 'cert_'). '.pem'; |
205
|
|
|
$key = tempnam($dir, 'key_') . '.pem'; |
206
|
|
|
file_put_contents($cert, "{$this->certificate->publicKey}"); |
207
|
|
|
file_put_contents($key, "{$this->certificate->privateKey}"); |
208
|
|
|
$this->mail->sign( |
209
|
|
|
$cert, |
210
|
|
|
$key, |
211
|
|
|
'', |
212
|
|
|
'' |
213
|
|
|
); |
214
|
|
|
} |
215
|
|
|
if (!$this->mail->send()) { |
216
|
|
|
$msg = 'A mensagem não pode ser enviada. Mail Error: ' . $this->mail->ErrorInfo; |
217
|
|
|
!empty($cert) ? unlink($cert) : null; |
218
|
|
|
!empty($key) ? unlink($key) : null; |
219
|
|
|
throw new \RuntimeException($msg); |
220
|
|
|
} |
221
|
|
|
$this->mail->clearAllRecipients(); |
222
|
|
|
$this->mail->clearAttachments(); |
223
|
|
|
!empty($cert) ? unlink($cert) : null; |
224
|
|
|
!empty($key) ? unlink($key) : null; |
225
|
|
|
return true; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* Configure and send documents |
230
|
|
|
* @param \stdClass $config |
231
|
|
|
* @param string $xml |
232
|
|
|
* @param string $pdf |
233
|
|
|
* @param array $addresses |
234
|
|
|
* @param string $htmltemplate |
235
|
|
|
* @param null|string $pfx |
236
|
|
|
* @param null|string $password |
237
|
|
|
* @param null|PHPMailer $mailer |
238
|
|
|
* @return Mail |
239
|
|
|
*/ |
240
|
|
|
public static function sendMail( |
241
|
|
|
\stdClass $config, |
242
|
|
|
$xml, |
243
|
|
|
$pdf = '', |
244
|
|
|
array $addresses = [], |
245
|
|
|
$htmltemplate = '', |
246
|
|
|
$pfx = null, |
247
|
|
|
$password = null, |
248
|
|
|
PHPMailer $mailer = null |
249
|
|
|
) { |
250
|
|
|
$mail = new static($config, $mailer); |
251
|
|
|
$mail->loadDocuments($xml, $pdf); |
252
|
|
|
$mail->loadTemplate($htmltemplate); |
253
|
|
|
$mail->enableSignature($pfx, $password); |
254
|
|
|
$mail->send($addresses, false); |
255
|
|
|
return $mail; |
256
|
|
|
} |
257
|
|
|
} |
258
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.