├── LICENSE ├── README.md ├── application ├── controllers │ └── queue_email.php └── libraries │ └── MY_Email.php └── schema └── Schema.sql /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 izn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CodeIgniter Mail Queue 2 | ===================== 3 | 4 | General Information 5 | ------------------- 6 | 7 | CI Mail Queue is a simple library (extended from CI_Mail) to queue emails in database and send them in background with CronJobs. 8 | 9 | How to Use? 10 | ------------ 11 | 12 | Import the schema and add cronjobs. 13 | 14 | E.g.: 15 | - Send pending emails each 2 minutes. 16 | - */2 * * * * php /var/www/index.php queue_email/send_queue 17 | - Send failed emails each 5 minutes. 18 | - */5 * * * * php /var/www/index.php queue_email/retry_queue 19 | 20 | Enjoy! 21 | -------------------------------------------------------------------------------- /application/controllers/queue_email.php: -------------------------------------------------------------------------------- 1 | input->is_cli_request()) 10 | show_404(); 11 | 12 | $this->load->library('email'); 13 | 14 | } 15 | 16 | public function index() 17 | { 18 | // Huh? 19 | show_404(); 20 | } 21 | 22 | public function send_queue() 23 | { 24 | $this->email->send_queue(); 25 | } 26 | 27 | public function retry_queue() 28 | { 29 | $this->email->retry_queue(); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /application/libraries/MY_Email.php: -------------------------------------------------------------------------------- 1 | expiration = 60*5; 38 | $this->CI = & get_instance(); 39 | 40 | $this->CI->load->database('default'); 41 | } 42 | 43 | public function set_status($status) 44 | { 45 | $this->status = $status; 46 | return $this; 47 | } 48 | 49 | /** 50 | * Get 51 | * 52 | * Get queue emails. 53 | * @return mixed 54 | */ 55 | public function get($limit = NULL, $offset = NULL) 56 | { 57 | if ($this->status != FALSE) 58 | $this->CI->db->where('status', $this->status); 59 | 60 | $query = $this->CI->db->get("{$this->table_email_queue}", $limit, $offset); 61 | 62 | return $query->result(); 63 | } 64 | 65 | /** 66 | * Save 67 | * 68 | * Add queue email to database. 69 | * @return mixed 70 | */ 71 | public function send($skip_job = FALSE) 72 | { 73 | if ( $skip_job === TRUE ) { 74 | return parent::send(); 75 | } 76 | 77 | $date = date("Y-m-d H:i:s"); 78 | 79 | $to = is_array($this->_recipients) ? implode(", ", $this->_recipients) : $this->_recipients; 80 | $cc = implode(", ", $this->_cc_array); 81 | $bcc = implode(", ", $this->_bcc_array); 82 | 83 | $dbdata = array( 84 | 'to' => $to, 85 | 'cc' => $cc, 86 | 'bcc' => $bcc, 87 | 'message' => $this->_body, 88 | 'headers' => serialize($this->_headers), 89 | 'status' => 'pending', 90 | 'date' => $date 91 | ); 92 | 93 | return $this->CI->db->insert($this->table_email_queue, $dbdata); 94 | } 95 | 96 | /** 97 | * Start process 98 | * 99 | * Start php process to send emails 100 | * @return mixed 101 | */ 102 | public function start_process() 103 | { 104 | $filename = FCPATH . 'index.php'; 105 | $exec = shell_exec("{$this->phpcli} {$filename} {$this->main_controller} > /dev/null &"); 106 | 107 | return $exec; 108 | } 109 | 110 | /** 111 | * Send queue 112 | * 113 | * Send queue emails. 114 | * @return void 115 | */ 116 | public function send_queue() 117 | { 118 | $this->set_status('pending'); 119 | $emails = $this->get(); 120 | 121 | $this->CI->db->where('status', 'pending'); 122 | $this->CI->db->set('status', 'sending'); 123 | $this->CI->db->set('date', date("Y-m-d H:i:s")); 124 | $this->CI->db->update($this->table_email_queue); 125 | 126 | foreach ($emails as $email) 127 | { 128 | $recipients = explode(", ", $email->to); 129 | 130 | $cc = !empty($email->cc) ? explode(", ", $email->cc) : array(); 131 | $bcc = !empty($email->bcc) ? explode(", ", $email->bcc) : array(); 132 | 133 | $this->_headers = unserialize($email->headers); 134 | 135 | $this->to($recipients); 136 | $this->cc($cc); 137 | $this->bcc($bcc); 138 | 139 | $this->message($email->message); 140 | 141 | if ($this->send(TRUE)) { 142 | $status = 'sent'; 143 | } else { 144 | $status = 'failed'; 145 | } 146 | 147 | $this->CI->db->where('id', $email->id); 148 | 149 | $this->CI->db->set('status', $status); 150 | $this->CI->db->set('date', date("Y-m-d H:i:s")); 151 | $this->CI->db->update($this->table_email_queue); 152 | } 153 | } 154 | 155 | /** 156 | * Retry failed emails 157 | * 158 | * Resend failed or expired emails 159 | * @return void 160 | */ 161 | public function retry_queue() 162 | { 163 | $expire = (time() - $this->expiration); 164 | $date_expire = date("Y-m-d H:i:s", $expire); 165 | 166 | $this->CI->db->set('status', 'pending'); 167 | $this->CI->db->where("(date < '{$date_expire}' AND status = 'sending')"); 168 | $this->CI->db->or_where("status = 'failed'"); 169 | 170 | $this->CI->db->update($this->table_email_queue); 171 | 172 | log_message('debug', 'Email queue retrying...'); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /schema/Schema.sql: -------------------------------------------------------------------------------- 1 | delimiter $$ 2 | 3 | CREATE TABLE `email_queue` ( 4 | `id` int(11) NOT NULL AUTO_INCREMENT, 5 | `to` varchar(255) NOT NULL, 6 | `cc` varchar(255) DEFAULT NULL, 7 | `bcc` varchar(255) DEFAULT NULL, 8 | `message` text NOT NULL, 9 | `status` enum('pending','sending','sent','failed') DEFAULT NULL, 10 | `date` datetime DEFAULT NULL, 11 | `headers` text, 12 | PRIMARY KEY (`id`) 13 | ) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8$$ --------------------------------------------------------------------------------