PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/inc/Mail/Queue.php

https://github.com/chregu/fluxcms
PHP | 536 lines | 165 code | 53 blank | 318 comment | 17 complexity | fb4c326f4c5046dffe3f365632f8c706 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, Apache-2.0, LGPL-2.1
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PEAR :: Mail :: Queue |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license, |
  9. // | that is bundled with this package in the file LICENSE, and is |
  10. // | available at through the world-wide-web at |
  11. // | http://www.php.net/license/3_0.txt. |
  12. // | If you did not receive a copy of the PHP license and are unable to |
  13. // | obtain it through the world-wide-web, please send a note to |
  14. // | license@php.net so we can mail you a copy immediately. |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Radek Maciaszek <chief@php.net> |
  17. // | Lorenzo Alberton <l dot alberton at quipo dot it> |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: Queue.php,v 1.15 2004/07/27 08:58:03 quipo Exp $
  21. /**
  22. * Class for handle mail queue managment.
  23. * Wrapper for Pear::Mail and Pear::DB.
  24. * Could load, save and send saved mails in background
  25. * and also backup some mails.
  26. *
  27. * Mail queue class put mails in a temporary
  28. * container waiting to be fed to the MTA (Mail Transport Agent)
  29. * and send them later (eg. every few minutes) by crontab or in other way.
  30. *
  31. * -------------------------------------------------------------------------
  32. * A basic usage example:
  33. * -------------------------------------------------------------------------
  34. *
  35. * $container_options = array(
  36. * 'type' => 'db',
  37. * 'database' => 'dbname',
  38. * 'phptype' => 'mysql',
  39. * 'username' => 'root',
  40. * 'password' => '',
  41. * 'mail_table' => 'mail_queue'
  42. * );
  43. * //optionally, a 'dns' string can be provided instead of db parameters.
  44. * //look at DB::connect() method or at DB or MDB docs for details.
  45. * //you could also use mdb container instead db
  46. *
  47. * $mail_options = array(
  48. * 'driver' => 'smtp',
  49. * 'host' => 'your_smtp_server.com',
  50. * 'port' => 25,
  51. * 'auth' => false,
  52. * 'username' => '',
  53. * 'password' => ''
  54. * );
  55. *
  56. * $mail_queue =& new Mail_Queue($container_options, $mail_options);
  57. * *****************************************************************
  58. * // Here the code differentiates wrt you want to add an email to the queue
  59. * // or you want to send the emails that already are in the queue.
  60. * *****************************************************************
  61. * // TO ADD AN EMAIL TO THE QUEUE
  62. * *****************************************************************
  63. * $from = 'user@server.com';
  64. * $from_name = 'admin';
  65. * $recipient = 'recipient@other_server.com';
  66. * $recipient_name = 'recipient';
  67. * $message = 'Test message';
  68. * $from_params = empty($from_name) ? '"'.$from_name.'" <'.$from.'>' : '<'.$from.'>';
  69. * $recipient_params = empty($recipient_name) ? '"'.$recipient_name.'" <'.$recipient.'>' : '<'.$recipient.'>';
  70. * $hdrs = array( 'From' => $from_params,
  71. * 'To' => $recipient_params,
  72. * 'Subject' => "test message body" );
  73. * $mime =& new Mail_mime();
  74. * $mime->setTXTBody($message);
  75. * $body = $mime->get();
  76. * $hdrs = $mime->headers($hdrs);
  77. *
  78. * // Put message to queue
  79. * $mail_queue->put( $from, $recipient, $hdrs, $body );
  80. * //Also you could put this msg in more advanced mode [look at Mail_Queue docs for details]
  81. * $seconds_to_send = 3600;
  82. * $delete_after_send = false;
  83. * $id_user = 7;
  84. * $mail_queue->put( $from, $recipient, $hdrs, $body, $seconds_to_send, $delete_after_send, $id_user );
  85. *
  86. * *****************************************************************
  87. * // TO SEND EMAILS IN THE QUEUE
  88. * *****************************************************************
  89. * // How many mails could we send each time
  90. * $max_ammount_mails = 50;
  91. * $mail_queue =& new Mail_Queue($container_options, $mail_options);
  92. * $mail_queue->sendMailsInQueue($max_ammount_mails);
  93. * *****************************************************************
  94. *
  95. * // for more examples look to docs directory
  96. *
  97. * // end usage example
  98. * -------------------------------------------------------------------------
  99. *
  100. * @version $Revision: 1.15 $
  101. * $Id: Queue.php,v 1.15 2004/07/27 08:58:03 quipo Exp $
  102. * @author Radek Maciaszek <chief@php.net>
  103. */
  104. /**
  105. * This is special constant define start offset for limit sql queries to
  106. * get mails.
  107. */
  108. define('MAILQUEUE_START', 0);
  109. /**
  110. * You can specify how many mails will be loaded to
  111. * queue else object use this constant for load all mails from db.
  112. */
  113. define('MAILQUEUE_ALL', -1);
  114. /**
  115. * When you put new mail to queue you could specify user id who send e-mail.
  116. * Else you could use system id: MAILQUEUE_SYSTEM or user unknown id: MAILQUEUE_UNKNOWN
  117. */
  118. define('MAILQUEUE_SYSTEM', -1);
  119. define('MAILQUEUE_UNKNOWN', -2);
  120. /**
  121. * This constant tells Mail_Queue how many times should try
  122. * to send mails again if was any errors before.
  123. */
  124. define('MAILQUEUE_TRY', 5);
  125. /**
  126. * MAILQUEUE_ERROR constants
  127. */
  128. define('MAILQUEUE_ERROR', -1);
  129. define('MAILQUEUE_ERROR_NO_DRIVER', -2);
  130. define('MAILQUEUE_ERROR_NO_CONTAINER', -3);
  131. define('MAILQUEUE_ERROR_CANNOT_INITIALIZE', -4);
  132. define('MAILQUEUE_ERROR_NO_OPTIONS', -5);
  133. define('MAILQUEUE_ERROR_CANNOT_CONNECT', -6);
  134. define('MAILQUEUE_ERROR_QUERY_FAILED', -7);
  135. define('MAILQUEUE_ERROR_UNEXPECTED', -8);
  136. define('MAILQUEUE_ERROR_CANNOT_SEND_MAIL', -9);
  137. require_once 'PEAR.php';
  138. require_once 'Mail.php';
  139. require_once 'Mail/mime.php';
  140. /**
  141. * Mail_Queue - base class for mail queue managment.
  142. *
  143. * @author Radek Maciaszek <wodzu@tonet.pl>
  144. * @version $Id: Queue.php,v 1.15 2004/07/27 08:58:03 quipo Exp $
  145. * @package Mail_Queue
  146. * @access public
  147. */
  148. class Mail_Queue extends PEAR
  149. {
  150. // {{{ Class vars
  151. /**
  152. * Mail options: smtp, mail etc. see Mail::factory
  153. *
  154. * @var array
  155. */
  156. var $mail_options;
  157. /**
  158. * Mail_Queue_Container
  159. *
  160. * @var object
  161. */
  162. var $container;
  163. /**
  164. * Reference to Pear_Mail object
  165. *
  166. * @var object
  167. */
  168. var $send_mail;
  169. /**
  170. * Pear error mode (when raiseError is called)
  171. * (see PEAR doc)
  172. *
  173. * @var int $_pearErrorMode
  174. * @access private
  175. */
  176. var $pearErrorMode = PEAR_ERROR_RETURN;
  177. // }}}
  178. // {{{ Mail_Queue
  179. /**
  180. * Mail_Queue constructor
  181. *
  182. * @param array $container_options Mail_Queue container options
  183. * @param array $mail_options How send mails.
  184. *
  185. * @return mixed True on success else PEAR error class.
  186. *
  187. * @access public
  188. */
  189. function Mail_Queue($container_options, $mail_options)
  190. {
  191. $this->PEAR();
  192. if (isset($mail_options['pearErrorMode'])) {
  193. $this->pearErrorMode = $mail_options['pearErrorMode'];
  194. // ugly hack to propagate 'pearErrorMode'
  195. $container_options['pearErrorMode'] = $mail_options['pearErrorMode'];
  196. }
  197. if (!is_array($mail_options) || !isset($mail_options['driver'])) {
  198. return new Mail_Queue_Error(MAILQUEUE_ERROR_NO_DRIVER,
  199. $this->pearErrorMode, E_USER_ERROR, __FILE__, __LINE__);
  200. }
  201. $this->mail_options = $mail_options;
  202. if (!is_array($container_options) || !isset($container_options['type'])) {
  203. return new Mail_Queue_Error(MAILQUEUE_ERROR_NO_CONTAINER,
  204. $this->pearErrorMode, E_USER_ERROR, __FILE__, __LINE__);
  205. }
  206. $container_type = strtolower($container_options['type']);
  207. $container_class = 'Mail_Queue_Container_' . $container_type;
  208. $container_classfile = $container_type . '.php';
  209. include_once 'Mail/Queue/Container/' . $container_classfile;
  210. $this->container = new $container_class($container_options);
  211. if(PEAR::isError($this->container)) {
  212. return new Mail_Queue_Error(MAILQUEUE_ERROR_CANNOT_INITIALIZE,
  213. $this->pearErrorMode, E_USER_ERROR, __FILE__, __LINE__);
  214. }
  215. return true;
  216. }
  217. // }}}
  218. // {{{ _Mail_Queue()
  219. /**
  220. * Mail_Queue desctructor
  221. *
  222. * @return void
  223. * @access public
  224. */
  225. function _Mail_Queue()
  226. {
  227. unset($this);
  228. }
  229. // }}}
  230. // {{{ factorySendMail()
  231. /**
  232. * Provides an interface for generating Mail:: objects of various
  233. * types see Mail::factory()
  234. *
  235. * @return void
  236. *
  237. * @access public
  238. */
  239. function factorySendMail()
  240. {
  241. $options = $this->mail_options;
  242. unset($options['driver']);
  243. $this->send_mail =& Mail::factory($this->mail_options['driver'], $options);
  244. }
  245. // }}}
  246. // {{{ setBufferSize()
  247. /**
  248. * Keep memory usage under control. You can set the max number
  249. * of mails that can be in the preload buffer at any given time.
  250. * It won't limit the number of mails you can send, just the
  251. * internal buffer size.
  252. *
  253. * @param integer $size Optional - internal preload buffer size
  254. **/
  255. function setBufferSize($size = 10)
  256. {
  257. $this->container->buffer_size = $size;
  258. }
  259. // }}}
  260. // {{{ sendMailsInQueue()
  261. /**
  262. * Send mails fom queue.
  263. *
  264. * Mail_Queue::sendMailsInQueue()
  265. *
  266. * @param integer $limit Optional - max limit mails send.
  267. * This is the max number of emails send by
  268. * this function.
  269. * @param integer $offset Optional - you could load mails from $offset (by id)
  270. * @param integer $try Optional - hoh many times mailqueu should try send
  271. * each mail. If mail was sent succesful it will be delete
  272. * from Mail_Queue.
  273. * @return mixed True on success else MAILQUEUE_ERROR object.
  274. **/
  275. function sendMailsInQueue($limit = MAILQUEUE_ALL, $offset = MAILQUEUE_START,
  276. $try = MAILQUEUE_TRY)
  277. {
  278. $this->container->setOption($limit, $offset, $try);
  279. while ($mail = $this->get()) {
  280. $this->container->countSend($mail);
  281. $result = $this->sendMail($mail);
  282. if (!PEAR::isError($result)) {
  283. $this->container->setAsSent($mail);
  284. if($mail->isDeleteAfterSend()) {
  285. $this->deleteMail($mail->getId());
  286. }
  287. } else {
  288. PEAR::raiseError(
  289. 'Error in sending mail: '.$result->getMessage(),
  290. MAILQUEUE_ERROR_CANNOT_SEND_MAIL, PEAR_ERROR_TRIGGER,
  291. E_USER_NOTICE);
  292. }
  293. }
  294. return true;
  295. }
  296. // }}}
  297. // {{{ sendMailById()
  298. /**
  299. * Send Mail by $id identifier. (bypass Mail_Queue)
  300. *
  301. * @param integer $id Mail identifier
  302. * @param bool $set_as_sent
  303. * @return bool true on success else false
  304. *
  305. * @access public
  306. */
  307. function sendMailById($id, $set_as_sent=true)
  308. {
  309. $mail =& $this->container->getMailById($id);
  310. $sent = $this->sendMail($mail);
  311. if ($sent and $set_as_sent) {
  312. $this->container->setAsSent($mail);
  313. }
  314. return $sent;
  315. }
  316. // }}}
  317. // {{{ sendMail()
  318. /**
  319. * Send mail from MailBody object
  320. *
  321. * @param object MailBody object
  322. * @return mixed True on success else pear error class
  323. *
  324. * @access public
  325. */
  326. function sendMail($mail)
  327. {
  328. $recipient = $mail->getRecipient();
  329. bx_log::logNewsletter("Mail_Queue, sending to: " . $recipient);
  330. $hdrs = $mail->getHeaders();
  331. $body = $mail->getBody();
  332. if (empty($this->send_mail)) {
  333. $this->factorySendMail();
  334. }
  335. return $this->send_mail->send($recipient, $hdrs, $body);
  336. }
  337. // }}}
  338. // {{{ get()
  339. /**
  340. * Get next mail from queue. The emails are preloaded
  341. * in a buffer for better performances.
  342. *
  343. * @return object Mail_Queue_Container or error object
  344. * @throw MAILQUEUE_ERROR
  345. * @access public
  346. */
  347. function get()
  348. {
  349. return $this->container->get();
  350. }
  351. // }}}
  352. // {{{ put()
  353. /**
  354. * Put new mail in queue.
  355. *
  356. * @see Mail_Queue_Container::put()
  357. *
  358. * @param string $time_to_send When mail have to be send
  359. * @param integer $id_user Sender id
  360. * @param string $ip Sender ip
  361. * @param string $from Sender e-mail
  362. * @param string $to Reciepient e-mail
  363. * @param string $hdrs Mail headers (in RFC)
  364. * @param string $body Mail body (in RFC)
  365. * @return mixed ID of the record where this mail has been put
  366. * or Mail_Queue_Error on error
  367. *
  368. * @access public
  369. **/
  370. function put($from, $to, $hdrs, $body, $sec_to_send=0, $delete_after_send=true, $id_user=MAILQUEUE_SYSTEM)
  371. {
  372. $ip = getenv('REMOTE_ADDR');
  373. $time_to_send = date("Y-m-d G:i:s", time() + $sec_to_send);
  374. return $this->container->put( $time_to_send, $id_user,
  375. $ip, $from, $to, serialize($hdrs),
  376. serialize($body), $delete_after_send );
  377. }
  378. // }}}
  379. // {{{ deleteMail()
  380. /**
  381. * Delete mail from queue database
  382. *
  383. * @param integer $id Maila identifier
  384. * @return boolean
  385. *
  386. * @access private
  387. */
  388. function deleteMail($id)
  389. {
  390. return $this->container->deleteMail($id);
  391. }
  392. // }}}
  393. // {{{ isError()
  394. /**
  395. * Tell whether a result code from a Mail_Queue method is an error
  396. *
  397. * @param int $value result code
  398. * @return boolean whether $value is an MAILQUEUE_ERROR
  399. * @access public
  400. */
  401. function isError($value)
  402. {
  403. return (is_object($value) && is_a($value, 'pear_error'));
  404. }
  405. // }}}
  406. // {{{ errorMessage()
  407. /**
  408. * Return a textual error message for a MDB error code
  409. *
  410. * @param int $value error code
  411. * @return string error message, or false if the error code was
  412. * not recognized
  413. * @access public
  414. */
  415. function errorMessage($value)
  416. {
  417. static $errorMessages;
  418. if (!isset($errorMessages)) {
  419. $errorMessages = array(
  420. MAILQUEUE_ERROR => 'unknown error',
  421. MAILQUEUE_ERROR_NO_DRIVER => 'No mail driver specified',
  422. MAILQUEUE_ERROR_NO_CONTAINER => 'No container specified',
  423. MAILQUEUE_ERROR_CANNOT_INITIALIZE => 'Cannot initialize container',
  424. MAILQUEUE_ERROR_NO_OPTIONS => 'No container options specified',
  425. MAILQUEUE_ERROR_CANNOT_CONNECT => 'Cannot connect to database',
  426. MAILQUEUE_ERROR_QUERY_FAILED => 'db query failed',
  427. MAILQUEUE_ERROR_UNEXPECTED => 'Unexpected class',
  428. MAILQUEUE_ERROR_CANNOT_SEND_MAIL => 'Cannot send email',
  429. );
  430. }
  431. if (Mail_Queue::isError($value)) {
  432. $value = $value->getCode();
  433. }
  434. return(isset($errorMessages[$value]) ?
  435. $errorMessages[$value] : $errorMessages[MAILQUEUE_ERROR]);
  436. }
  437. // }}}
  438. /*
  439. function raiseError($msg, $code = null, $file = null, $line = null, $mode = null)
  440. {
  441. if ($file !== null) {
  442. $err = PEAR::raiseError(sprintf("%s [%s on line %d].", $msg, $file, $line), $code, $mode);
  443. } else {
  444. $err = PEAR::raiseError(sprintf("%s", $msg), $code, $mode);
  445. }
  446.         return $err;
  447. }
  448. */
  449. }
  450. /**
  451. * Mail_Queue_Error implements a class for reporting error
  452. * messages.
  453. *
  454. * @package Mail_Queue
  455. * @category Mail
  456. */
  457. class Mail_Queue_Error extends PEAR_Error
  458. {
  459. // {{{ constructor
  460. /**
  461. * Mail_Queue_Error constructor.
  462. *
  463. * @param mixed $code Mail_Queue error code, or string with error message.
  464. * @param integer $mode what 'error mode' to operate in
  465. * @param integer $level what error level to use for
  466. * $mode & PEAR_ERROR_TRIGGER
  467. * @param string $debuginfo additional debug info
  468. */
  469. function Mail_Queue_Error($code = MAILQUEUE_ERROR, $mode = PEAR_ERROR_RETURN,
  470. $level = E_USER_NOTICE, $file=__FILE__, $line=__LINE__, $debuginfo='')
  471. {
  472. $debuginfo .= (empty($debuginfo) ? '' : ' - '). 'FILE: '.$file.', LINE: '.$line;
  473. if (is_int($code)) {
  474. $this->PEAR_Error('Mail Queue Error: ' . Mail_Queue::errorMessage($code),
  475. $code, $mode, $level, $debuginfo);
  476. } else {
  477. $this->PEAR_Error('Mail Queue Error: ' . $code, MAILQUEUE_ERROR, $mode,
  478. $level, $debuginfo);
  479. }
  480. }
  481. // }}}
  482. }
  483. ?>