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-2016 XOOPS Project (www.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 <onokazu@xoops.org>
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();
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 = array();
137: $this->toEmails = array();
138: $this->headers = array();
139: $this->subject = '';
140: $this->body = '';
141: $this->errors = array();
142: $this->success = array();
143: $this->isMail = false;
144: $this->isPM = false;
145: $this->assignedTags = array();
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
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)) {
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)
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: if (!$this->multimailer->send()) {
450: $this->errors[] = $this->multimailer->ErrorInfo;
451:
452: return false;
453: }
454:
455: return true;
456: }
457:
458: // public
459: /**
460: * @param bool $ashtml
461: *
462: * @return string
463: */
464: public function getErrors($ashtml = true)
465: {
466: if (!$ashtml) {
467: return $this->errors;
468: } else {
469: if (!empty($this->errors)) {
470: $ret = '<h4>' . _ERRORS . '</h4>';
471: foreach ($this->errors as $error) {
472: $ret .= $error . '<br>';
473: }
474: } else {
475: $ret = '';
476: }
477:
478: return $ret;
479: }
480: }
481:
482: // public
483: /**
484: * @param bool $ashtml
485: *
486: * @return string
487: */
488: public function getSuccess($ashtml = true)
489: {
490: if (!$ashtml) {
491: return $this->success;
492: } else {
493: $ret = '';
494: if (!empty($this->success)) {
495: foreach ($this->success as $suc) {
496: $ret .= $suc . '<br>';
497: }
498: }
499:
500: return $ret;
501: }
502: }
503:
504: // public
505: /**
506: * @param $tag
507: * @param null $value
508: */
509: public function assign($tag, $value = null)
510: {
511: if (is_array($tag)) {
512: foreach ($tag as $k => $v) {
513: $this->assign($k, $v);
514: }
515: } else {
516: if (!empty($tag) && isset($value)) {
517: $tag = strtoupper(trim($tag));
518: // RMV-NOTIFY
519: // TEMPORARY FIXME: until the X_tags are all in here
520: // if ( substr($tag, 0, 2) != "X_" ) {
521: $this->assignedTags[$tag] = $value;
522: // }
523: }
524: }
525: }
526:
527: // public
528: /**
529: * @param $value
530: */
531: public function addHeaders($value)
532: {
533: $this->headers[] = trim($value) . $this->LE;
534: }
535:
536: // public
537: /**
538: * @param $email
539: */
540: public function setToEmails($email)
541: {
542: if (!is_array($email)) {
543: if (preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+([\.][a-z0-9-]+)+$/i", $email)) {
544: array_push($this->toEmails, $email);
545: }
546: } else {
547: foreach ($email as $e) {
548: $this->setToEmails($e);
549: }
550: }
551: }
552:
553: // public
554: /**
555: * @param $user
556: */
557: public function setToUsers($user)
558: {
559: if (!is_array($user)) {
560: if (strtolower(get_class($user)) === 'xoopsuser') {
561: array_push($this->toUsers, $user);
562: }
563: } else {
564: foreach ($user as $u) {
565: $this->setToUsers($u);
566: }
567: }
568: }
569:
570: // public
571: /**
572: * @param $group
573: */
574: public function setToGroups($group)
575: {
576: if (!is_array($group)) {
577: if (strtolower(get_class($group)) === 'xoopsgroup') {
578: /** @var XoopsMemberHandler $member_handler */
579: $member_handler = xoops_getHandler('member');
580: $this->setToUsers($member_handler->getUsersByGroup($group->getVar('groupid'), true));
581: }
582: } else {
583: foreach ($group as $g) {
584: $this->setToGroups($g);
585: }
586: }
587: }
588:
589: // abstract
590: // to be overridden by lang specific mail class, if needed
591: /**
592: * @param $text
593: *
594: * @return mixed
595: */
596: public function encodeFromName($text)
597: {
598: return $text;
599: }
600:
601: // abstract
602: // to be overridden by lang specific mail class, if needed
603: /**
604: * @param $text
605: *
606: * @return mixed
607: */
608: public function encodeSubject($text)
609: {
610: return $text;
611: }
612:
613: // abstract
614: // to be overridden by lang specific mail class, if needed
615: /**
616: * @param $text
617: */
618: public function encodeBody(&$text)
619: {
620: }
621: }
622: