Passed
Push — master ( 145306...a46cb4 )
by Michael
17:35 queued 09:16
created

XoopsMailer::setFromUser()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 1
1
<?php
2
/**
3
 * XOOPS mailer
4
 *
5
 * You may not change or alter any portion of this comment or credits
6
 * of supporting developers from this source code or any supporting source code
7
 * which is considered copyrighted (c) material of the original comment or credit authors.
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * @copyright       (c) 2000-2025 XOOPS Project (https://xoops.org)
13
 * @license             GNU GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html)
14
 * @package             kernel
15
 * @since               2.0.0
16
 * @author              Kazumi Ono (AKA onokazu) http://www.myweb.ne.jp/, http://jp.xoops.org/
17
 * @deprecated          use {@link XoopsMultiMailer} instead.
18
 */
19
20
defined('XOOPS_ROOT_PATH') || exit('Restricted access');
21
22
xoops_loadLanguage('mail');
23
24
/**
25
 * The new Multimailer class that will carry out the actual sending and will later replace this class.
26
 * If you're writing new code, please use that class instead.
27
 */
28
include_once $GLOBALS['xoops']->path('class/mail/xoopsmultimailer.php');
29
30
/**
31
 * Class for sending mail.
32
 *
33
 * Changed to use the facilities of  {@link XoopsMultiMailer}
34
 *
35
 * @package    class
36
 * @subpackage mail
37
 * @author     Kazumi Ono <[email protected]>
38
 */
39
class XoopsMailer
40
{
41
    /**
42
     * reference to a {@link XoopsMultiMailer}
43
     *
44
     * @var XoopsMultiMailer
45
     * @access private
46
     * @since  21.02.2003 14:14:13
47
     */
48
    public $multimailer;
49
    // sender email address
50
    // private
51
    public $fromEmail;
52
    // sender name
53
    // private
54
    public $fromName;
55
    // RMV-NOTIFY
56
    // sender UID
57
    // private
58
    public $fromUser;
59
    public $priority;
60
    // array of user class objects
61
    // private
62
    public $toUsers;
63
    // array of email addresses
64
    // private
65
    public $toEmails;
66
    // custom headers
67
    // private
68
    public $headers;
69
    // subject of mail
70
    // private
71
    public $subject;
72
    // body of mail
73
    // private
74
    public $body;
75
    // error messages
76
    // private
77
    public $errors;
78
    // messages upon success
79
    // private
80
    public $success;
81
    // private
82
    public $isMail;
83
    // private
84
    public $isPM;
85
    // private
86
    public $assignedTags;
87
    // private
88
    public $template;
89
    // private
90
    public $templatedir;
91
    public $LE;
92
    // protected
93
    public $charSet = 'iso-8859-1';
94
    // protected
95
    public $encoding = '8bit';
96
97
    /**
98
     * Constructor
99
     *
100
     * @return XoopsMailer
101
     */
102
    public function __construct()
103
    {
104
        $this->multimailer = new XoopsMultiMailer();
105
        $this->reset();
106
    }
107
108
    /**
109
     * PHP 4 style constructor compatibility shim
110
     *
111
     * @deprecated all callers should be using parent::__construct()
112
     */
113
    public function XoopsMailer()
114
    {
115
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
116
        trigger_error("Should call parent::__construct in {$trace[0]['file']} line {$trace[0]['line']},", E_USER_DEPRECATED);
117
        self::__construct();
0 ignored issues
show
Bug Best Practice introduced by
The method XoopsMailer::__construct() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

117
        self::/** @scrutinizer ignore-call */ 
118
              __construct();
Loading history...
118
    }
119
120
    /**
121
     * @param bool $value
122
     */
123
    public function setHTML($value = true)
124
    {
125
        $this->multimailer->isHTML($value);
126
    }
127
128
    // public
129
    // reset all properties to default
130
    public function reset()
131
    {
132
        $this->fromEmail    = '';
133
        $this->fromName     = '';
134
        $this->fromUser     = null; // RMV-NOTIFY
135
        $this->priority     = '';
136
        $this->toUsers      = [];
137
        $this->toEmails     = [];
138
        $this->headers      = [];
139
        $this->subject      = '';
140
        $this->body         = '';
141
        $this->errors       = [];
142
        $this->success      = [];
143
        $this->isMail       = false;
144
        $this->isPM         = false;
145
        $this->assignedTags = [];
146
        $this->template     = '';
147
        $this->templatedir  = '';
148
        // Change below to \r\n if you have problem sending mail
149
        $this->LE = "\n";
150
    }
151
152
    // public
153
    /**
154
     * @param null $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
155
     */
156
    public function setTemplateDir($value = null)
157
    {
158
        if ($value === null && is_object($GLOBALS['xoopsModule'])) {
159
            $value = $GLOBALS['xoopsModule']->getVar('dirname', 'n');
160
        } else {
161
            $value = str_replace(DIRECTORY_SEPARATOR, '/', $value);
162
        }
163
        $this->templatedir = $value;
164
    }
165
166
    // private
167
    /**
168
     * @return bool|string
169
     */
170
    public function getTemplatePath()
171
    {
172
        if (!$path = $this->templatedir) {
173
            $path = XOOPS_ROOT_PATH . '/language/';
174
        } elseif (false === strpos($path, '/')) {
175
            $path = XOOPS_ROOT_PATH . '/modules/' . $path . '/language/';
176
        } elseif (substr($path, -1, 1) !== '/') {
177
            $path .= '/';
178
        }
179
        if (file_exists($path . $GLOBALS['xoopsConfig']['language'] . '/mail_template/' . $this->template)) {
180
            return $path . $GLOBALS['xoopsConfig']['language'] . '/mail_template/' . $this->template;
181
        } elseif (file_exists($path . 'english/mail_template/' . $this->template)) {
182
            return $path . 'english/mail_template/' . $this->template;
183
        } elseif (file_exists($path . $this->template)) {
184
            return $path . $this->template;
185
        } else {
186
            return false;
187
        }
188
    }
189
190
    // public
191
    /**
192
     * @param $value
193
     */
194
    public function setTemplate($value)
195
    {
196
        $this->template = $value;
197
    }
198
199
    // pupblic
200
    /**
201
     * @param $value
202
     */
203
    public function setFromEmail($value)
204
    {
205
        $this->fromEmail = trim($value);
206
    }
207
208
    // public
209
    /**
210
     * @param $value
211
     */
212
    public function setFromName($value)
213
    {
214
        $this->fromName = trim($value);
215
    }
216
217
    // RMV-NOTIFY
218
    // public
219
    /**
220
     * @param $user
221
     */
222
    public function setFromUser($user)
223
    {
224
        if (strtolower(get_class($user)) === 'xoopsuser') {
225
            $this->fromUser = &$user;
226
        }
227
    }
228
229
    // public
230
    /**
231
     * @param $value
232
     */
233
    public function setPriority($value)
234
    {
235
        $this->priority = trim($value);
236
    }
237
238
    // public
239
    /**
240
     * @param $value
241
     */
242
    public function setSubject($value)
243
    {
244
        $this->subject = trim($value);
245
    }
246
247
    // public
248
    /**
249
     * @param $value
250
     */
251
    public function setBody($value)
252
    {
253
        $this->body = trim($value);
254
    }
255
256
    // public
257
    public function useMail()
258
    {
259
        $this->isMail = true;
260
    }
261
262
    // public
263
    public function usePM()
264
    {
265
        $this->isPM = true;
266
    }
267
268
    // public
269
    /**
270
     * @param bool $debug
271
     *
272
     * @return bool
273
     */
274
    public function send($debug = false)
275
    {
276
        global $xoopsConfig;
277
        if ($this->body == '' && $this->template == '') {
278
            if ($debug) {
279
                $this->errors[] = _MAIL_MSGBODY;
280
            }
281
            return false;
282
        } elseif ($this->template != '') {
283
            $path = $this->getTemplatePath();
284
            if (!is_string($path) || !file_exists($path) || !is_readable($path)) {
285
                if ($debug) {
286
                    $this->errors[] = _MAIL_FAILOPTPL;
287
                }
288
                return false;
289
            }
290
291
            $fd = fopen($path, 'rb');
292
            if ($fd === false) {
293
                if ($debug) {
294
                    $this->errors[] = _MAIL_FAILOPTPL;
295
                }
296
                return false;
297
            }
298
            $this->setBody(fread($fd, filesize($path)));
299
            fclose($fd);
300
        }
301
302
        // for sending mail only
303
        $headers = '';
304
        if ($this->isMail || !empty($this->toEmails)) {
305
            if (!empty($this->priority)) {
306
                $this->headers[] = 'X-Priority: ' . $this->priority;
307
            }
308
            // $this->headers[] = "X-Mailer: PHP/".phpversion();
309
            // $this->headers[] = "Return-Path: ".$this->fromEmail;
310
            $headers = implode($this->LE, $this->headers);
311
        }
312
        // TODO: we should have an option of no-reply for private messages and emails
313
        // to which we do not accept replies.  e.g. the site admin doesn't want a
314
        // a lot of message from people trying to unsubscribe.  Just make sure to
315
        // give good instructions in the message.
316
        // add some standard tags (user-dependent tags are included later)
317
        global $xoopsConfig;
318
319
        $this->assign('X_ADMINMAIL', $xoopsConfig['adminmail']);
320
        $this->assign('X_SITENAME', $xoopsConfig['sitename']);
321
        $this->assign('X_SITEURL', XOOPS_URL . '/');
322
        // TODO: also X_ADMINNAME??
323
        // TODO: X_SIGNATURE, X_DISCLAIMER ?? - these are probably best
324
        // done as includes if mail templates ever get this sophisticated
325
        // replace tags with actual values
326
        foreach ($this->assignedTags as $k => $v) {
327
            $this->body    = str_replace('{' . $k . '}', $v, $this->body);
328
            $this->subject = str_replace('{' . $k . '}', $v, $this->subject);
329
        }
330
        $this->body = str_replace("\r\n", "\n", $this->body);
331
        $this->body = str_replace("\r", "\n", $this->body);
332
        $this->body = str_replace("\n", $this->LE, $this->body);
333
        // send mail to specified mail addresses, if any
334
        foreach ($this->toEmails as $mailaddr) {
335
            if (!$this->sendMail($mailaddr, $this->subject, $this->body, $headers)) {
336
                if ($debug) {
337
                    $this->errors[] = sprintf(_MAIL_SENDMAILNG, $mailaddr);
338
                }
339
            } else {
340
                if ($debug) {
341
                    $this->success[] = sprintf(_MAIL_MAILGOOD, $mailaddr);
342
                }
343
            }
344
        }
345
        // send message to specified users, if any
346
        // NOTE: we don't send to LIST of recipients, because the tags
347
        // below are dependent on the user identity; i.e. each user
348
        // receives (potentially) a different message
349
        foreach ($this->toUsers as $user) {
350
            // set some user specific variables
351
            $subject = str_replace('{X_UNAME}', $user->getVar('uname'), $this->subject);
352
            $text    = str_replace('{X_UID}', $user->getVar('uid'), $this->body);
353
            $text    = str_replace('{X_UEMAIL}', $user->getVar('email'), $text);
354
            $text    = str_replace('{X_UNAME}', $user->getVar('uname'), $text);
355
            if ($user->getVar('name') == '') {
356
                $x_name = $user->getVar('uname');
357
            } else {
358
                $x_name = $user->getVar('name');
359
            }
360
            $text    = str_replace('{X_NAME}', $x_name, $text);
361
            $text    = str_replace('{X_UACTLINK}', XOOPS_URL . '/register.php?op=actv&id=' . $user->getVar('uid') . '&actkey=' . $user->getVar('actkey'), $text);
362
            // send mail
363
            if ($this->isMail) {
364
                if (!$this->sendMail($user->getVar('email'), $subject, $text, $headers)) {
365
                    if ($debug) {
366
                        $this->errors[] = sprintf(_MAIL_SENDMAILNG, $user->getVar('uname'));
367
                    }
368
                } else {
369
                    if ($debug) {
370
                        $this->success[] = sprintf(_MAIL_MAILGOOD, $user->getVar('uname'));
371
                    }
372
                }
373
            }
374
            // send private message
375
            if ($this->isPM) {
376
                if (!$this->sendPM($user->getVar('uid'), $subject, $text)) {
377
                    if ($debug) {
378
                        $this->errors[] = sprintf(_MAIL_SENDPMNG, $user->getVar('uname'));
379
                    }
380
                } else {
381
                    if ($debug) {
382
                        $this->success[] = sprintf(_MAIL_PMGOOD, $user->getVar('uname'));
383
                    }
384
                }
385
            }
386
            flush();
387
        }
388
        return !(count($this->errors) > 0);
389
    }
390
391
    // private
392
    /**
393
     * @param $uid
394
     * @param $subject
395
     * @param $body
396
     *
397
     * @return bool
398
     */
399
    public function sendPM($uid, $subject, $body)
400
    {
401
        global $xoopsUser;
402
        $pm_handler = xoops_getHandler('privmessage');
403
        $pm         = $pm_handler->create();
404
        $pm->setVar('subject', $subject);
405
        // RMV-NOTIFY
406
        $pm->setVar('from_userid', !empty($this->fromUser) ? $this->fromUser->getVar('uid') : (empty($xoopsUser) ? 1 : $xoopsUser->getVar('uid')));
407
        $pm->setVar('msg_text', $body);
408
        $pm->setVar('to_userid', $uid);
409
        if (!$pm_handler->insert($pm)) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of $pm_handler->insert($pm) targeting XoopsObjectHandler::insert() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
410
            return false;
411
        }
412
413
        return true;
414
    }
415
416
    /**
417
     * Send email
418
     *
419
     * Uses the new XoopsMultiMailer
420
     *
421
     * @param $email
422
     * @param $subject
423
     * @param $body
424
     * @param $headers
425
     *
426
     * @return bool
427
     */
428
    public function sendMail($email, $subject, $body, $headers)
0 ignored issues
show
Unused Code introduced by
The parameter $headers is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

428
    public function sendMail($email, $subject, $body, /** @scrutinizer ignore-unused */ $headers)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
429
    {
430
        $subject = $this->encodeSubject($subject);
431
        $this->encodeBody($body);
432
        $this->multimailer->clearAllRecipients();
433
        $this->multimailer->addAddress($email);
434
        $this->multimailer->Subject = $subject;
435
        $this->multimailer->Body = $body;
436
        $this->multimailer->CharSet = $this->charSet;
437
        $this->multimailer->Encoding = $this->encoding;
438
        if (!empty($this->fromName)) {
439
            $this->multimailer->FromName = $this->encodeFromName($this->fromName);
440
        }
441
        if (!empty($this->fromEmail)) {
442
            $this->multimailer->Sender = $this->multimailer->From = $this->fromEmail;
443
        }
444
445
        $this->multimailer->clearCustomHeaders();
446
        foreach ($this->headers as $header) {
447
            $this->multimailer->addCustomHeader($header);
448
        }
449
        try {
450
            if (!$this->multimailer->send()) {
451
                $this->errors[] = $this->multimailer->ErrorInfo;
452
                return false;
453
            }
454
        } catch (\PHPMailer\PHPMailer\Exception $e) {
455
            // Normalize PHPMailer exceptions to XOOPS' error array
456
            $this->errors[] = $e->getMessage();
457
            return false;
458
        }
459
460
        return true;
461
    }
462
463
    // public
464
    /**
465
     * @param bool $ashtml
466
     *
467
     * @return string
468
     */
469
    public function getErrors($ashtml = true)
470
    {
471
        if (!$ashtml) {
472
            return $this->errors;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->errors returns the type array which is incompatible with the documented return type string.
Loading history...
473
        } else {
474
            if (!empty($this->errors)) {
475
                $ret = '<h4>' . _ERRORS . '</h4>';
476
                foreach ($this->errors as $error) {
477
                    $ret .= $error . '<br>';
478
                }
479
            } else {
480
                $ret = '';
481
            }
482
483
            return $ret;
484
        }
485
    }
486
487
    // public
488
    /**
489
     * @param bool $ashtml
490
     *
491
     * @return string
492
     */
493
    public function getSuccess($ashtml = true)
494
    {
495
        if (!$ashtml) {
496
            return $this->success;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->success returns the type array which is incompatible with the documented return type string.
Loading history...
497
        } else {
498
            $ret = '';
499
            if (!empty($this->success)) {
500
                foreach ($this->success as $suc) {
501
                    $ret .= $suc . '<br>';
502
                }
503
            }
504
505
            return $ret;
506
        }
507
    }
508
509
    // public
510
    /**
511
     * @param      $tag
512
     * @param null $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
513
     */
514
    public function assign($tag, $value = null)
515
    {
516
        if (is_array($tag)) {
517
            foreach ($tag as $k => $v) {
518
                $this->assign($k, $v);
519
            }
520
        } else {
521
            if (!empty($tag) && isset($value)) {
522
                $tag = strtoupper(trim($tag));
523
                // RMV-NOTIFY
524
                // TEMPORARY FIXME: until the X_tags are all in here
525
                // if ( substr($tag, 0, 2) != "X_" ) {
526
                $this->assignedTags[$tag] = $value;
527
                // }
528
            }
529
        }
530
    }
531
532
    // public
533
    /**
534
     * @param $value
535
     */
536
    public function addHeaders($value)
537
    {
538
        $this->headers[] = trim($value) . $this->LE;
539
    }
540
541
    // public
542
    /**
543
     * @param $email
544
     */
545
    public function setToEmails($email)
546
    {
547
        if (!is_array($email)) {
548
            if (preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+([\.][a-z0-9-]+)+$/i", $email)) {
549
                array_push($this->toEmails, $email);
550
            }
551
        } else {
552
            foreach ($email as $e) {
553
                $this->setToEmails($e);
554
            }
555
        }
556
    }
557
558
    // public
559
    /**
560
     * @param $user
561
     */
562
    public function setToUsers($user)
563
    {
564
        if (!is_array($user)) {
565
            if (strtolower(get_class($user)) === 'xoopsuser') {
566
                array_push($this->toUsers, $user);
567
            }
568
        } else {
569
            foreach ($user as $u) {
570
                $this->setToUsers($u);
571
            }
572
        }
573
    }
574
575
    // public
576
    /**
577
     * @param $group
578
     */
579
    public function setToGroups($group)
580
    {
581
        if (!is_array($group)) {
582
            if (strtolower(get_class($group)) === 'xoopsgroup') {
583
                /** @var XoopsMemberHandler $member_handler */
584
                $member_handler = xoops_getHandler('member');
585
                $this->setToUsers($member_handler->getUsersByGroup($group->getVar('groupid'), true));
586
            }
587
        } else {
588
            foreach ($group as $g) {
589
                $this->setToGroups($g);
590
            }
591
        }
592
    }
593
594
    // abstract
595
    // to be overridden by lang specific mail class, if needed
596
    /**
597
     * @param $text
598
     *
599
     * @return mixed
600
     */
601
    public function encodeFromName($text)
602
    {
603
        return $text;
604
    }
605
606
    // abstract
607
    // to be overridden by lang specific mail class, if needed
608
    /**
609
     * @param $text
610
     *
611
     * @return mixed
612
     */
613
    public function encodeSubject($text)
614
    {
615
        return $text;
616
    }
617
618
    // abstract
619
    // to be overridden by lang specific mail class, if needed
620
    /**
621
     * @param $text
622
     */
623
    public function encodeBody(&$text) {}
0 ignored issues
show
Unused Code introduced by
The parameter $text is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

623
    public function encodeBody(/** @scrutinizer ignore-unused */ &$text) {}

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
624
}
625