]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/EmailMan/EmailManDelivery.php
Release 6.2.3
[Github/sugarcrm.git] / modules / EmailMan / EmailManDelivery.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38
39 require_once('include/SugarPHPMailer.php');
40
41 $test=false;
42 if (isset($_REQUEST['mode']) && $_REQUEST['mode']=='test') {
43         $test=true;
44 }
45 if (isset($_REQUEST['send_all']) && $_REQUEST['send_all']== true) {
46         $send_all= true;
47 }
48 else  {
49         $send_all=false; //if set to true email delivery will continue..to run until all email have been delivered.
50 }
51 $GLOBALS['log'] = LoggerManager::getLogger('SugarCRM');
52 $mail = new SugarPHPMailer();
53 $admin = new Administration();
54 $admin->retrieveSettings();
55 if (isset($admin->settings['massemailer_campaign_emails_per_run'])) {
56         $max_emails_per_run=$admin->settings['massemailer_campaign_emails_per_run'];
57 }
58 if (empty($max_emails_per_run)) {
59         $max_emails_per_run=500;//default
60 }
61 //save email copies?
62 $massemailer_email_copy=0;  //default: save copies of the email.
63 if (isset($admin->settings['massemailer_email_copy'])) {
64     $massemailer_email_copy=$admin->settings['massemailer_email_copy'];
65 }
66
67 $emailsPerSecond = 10;
68
69 $mail->setMailerForSystem();
70 $mail->From     = "no-reply@example.com";
71 $mail->FromName = "no-reply";
72 $mail->ContentType="text/html";
73
74 $campaign_id=null;
75 if (isset($_REQUEST['campaign_id']) && !empty($_REQUEST['campaign_id'])) {
76         $campaign_id=$_REQUEST['campaign_id'];
77 }
78
79 $db = DBManagerFactory::getInstance();
80 $timedate = TimeDate::getInstance();
81 $emailman = new EmailMan();
82
83     if($test){
84         //if this is in test mode, then
85         //find all the message that meet the following criteria.
86         //1. scheduled send date time is now
87         //2. campaign matches the current campaign
88         //3. recipient belongs to a propsect list of type test, attached to this campaign
89
90         $select_query =" SELECT em.* FROM emailman em";
91         $select_query.=" join prospect_list_campaigns plc on em.campaign_id = plc.campaign_id";
92         $select_query.=" join prospect_lists pl on pl.id = plc.prospect_list_id ";
93         $select_query.=" WHERE em.list_id = pl.id and pl.list_type = 'test'";
94         $select_query.=" AND em.send_date_time <= ". db_convert("'".$timedate->nowDb()."'" ,"datetime");
95         $select_query.=" AND (em.in_queue ='0' OR ( em.in_queue ='1' AND em.in_queue_date <= " .db_convert("'". $timedate->fromString("-1 day")->asDb() ."'" ,"datetime")."))";
96         $select_query.=" AND em.campaign_id='{$campaign_id}'";
97         $select_query.=" ORDER BY em.send_date_time ASC, em.user_id, em.list_id";
98     }else{
99         //this is not a test..
100         //find all the message that meet the following criteria.
101         //1. scheduled send date time is now
102         //2. were never processed or last attempt was 24 hours ago
103         $select_query =" SELECT *";
104         $select_query.=" FROM $emailman->table_name";
105         $select_query.=" WHERE send_date_time <= ". db_convert("'".TimeDate::getInstance()->nowDb()."'" ,"datetime");
106         $select_query.=" AND (in_queue ='0' OR ( in_queue ='1' AND in_queue_date <= " .db_convert("'". $timedate->fromString("-1 day")->asDb() ."'" ,"datetime")."))";
107
108         if (!empty($campaign_id)) {
109             $select_query.=" AND campaign_id='{$campaign_id}'";
110         }
111         $select_query.=" ORDER BY send_date_time ASC,user_id, list_id";
112
113     }
114
115 //bug 26926 fix start
116 DBManager::setQueryLimit(0);
117 //end bug fix
118
119 do {
120
121         $no_items_in_queue=true;
122
123         $result = $db->limitQuery($select_query,0,$max_emails_per_run);
124         global $current_user;
125         if(isset($current_user)){
126                 $temp_user = $current_user;
127         }
128         $current_user = new User();
129         $startTime = microtime(true);
130
131         while(($row = $db->fetchByAssoc($result))!= null){
132
133         //verify the queue item before further processing.
134         //we have found cases where users have taken away access to email templates while them message is in queue.
135         if (empty($row['campaign_id'])) {
136             $GLOBALS['log']->fatal('Skipping emailman entry with empty campaign id' . print_r($row,true));
137             continue;
138         }
139         if (empty($row['marketing_id'])) {
140             $GLOBALS['log']->fatal('Skipping emailman entry with empty marketing id' . print_r($row,true));
141             continue;  //do not process this row .
142         }
143
144         //fetch user that scheduled the campaign.
145         if(empty($current_user) or $row['user_id'] != $current_user->id){
146             $current_user->retrieve($row['user_id']);
147         }
148
149         if (!$emailman->verify_campaign($row['marketing_id'])) {
150             $GLOBALS['log']->fatal('Error verifying templates for the campaign, exiting');
151             continue;
152         }
153
154
155         //verify the email template too..
156         //find the template associated with marketing message. make sure that template has a subject and
157         //a non-empty body
158         if (!isset($template_status[$row['marketing_id']])) {
159             if (!class_exists('EmailMarketing')) {
160
161             }
162             $current_emailmarketing=new EmailMarketing();
163             $current_emailmarketing->retrieve($row['marketing_id']);
164
165             if (!class_exists('EmailTemplate')) {
166
167             }
168             $current_emailtemplate= new EmailTemplate();
169             $current_emailtemplate->retrieve($current_emailmarketing->template_id);
170
171         }
172
173                 //acquire a lock.
174                 //if the database does not support repeatable read isolation by default, we might get data that does not meet
175         //the criteria in the original query, and we care most about the in_queue_date and process_date_time,
176         //if they are null or in past(older than 24 horus) then we are okay.
177                 $lock_query="UPDATE emailman SET in_queue=1, in_queue_date='". $timedate->nowDb() ."' WHERE id = '${row['id']}'";
178                 $lock_query.=" AND (in_queue ='0' OR ( in_queue ='1' AND in_queue_date <= " .db_convert("'". $timedate->fromString("-1 day")->asDb() ."'" ,"datetime")."))";
179
180                 //if the query fails to execute.. terminate campaign email process.
181                 $lock_result=$db->query($lock_query,true,'Error acquiring a lock for emailman entry.');
182                 if ($db->dbType=='oci8') {
183                 } else {
184                         $lock_count=$db->getAffectedRowCount();
185                 }
186
187                 //do not process the message if unable to acquire lock.
188                 if ($lock_count!= 1) {
189                         $GLOBALS['log']->fatal("Error acquiring lock for the emailman entry, skipping email delivery. lock status=$lock_count " . print_r($row,true));
190                         continue;  //do not process this row we will examine it after 24 hrs. the email address based dupe check is in place too.
191                 }
192
193                 $no_items_in_queue=false;
194
195
196                 foreach($row as $name=>$value){
197                         $emailman->$name = $value;
198                 }
199
200                 //for the campaign process the supression lists.
201                 if (!isset($current_campaign_id) or empty($current_campaign_id) or $current_campaign_id != $row['campaign_id']) {
202                         $current_campaign_id= $row['campaign_id'];
203
204                         //is this email address suppressed?
205                         $plc_query= " SELECT prospect_list_id, prospect_lists.list_type,prospect_lists.domain_name FROM prospect_list_campaigns ";
206                         $plc_query.=" LEFT JOIN prospect_lists on prospect_lists.id = prospect_list_campaigns.prospect_list_id";
207                         $plc_query.=" WHERE ";
208                         $plc_query.=" campaign_id='{$current_campaign_id}' ";
209                         $plc_query.=" AND prospect_lists.list_type in ('exempt_address','exempt_domain')";
210                         $plc_query.=" AND prospect_list_campaigns.deleted=0";
211                         $plc_query.=" AND prospect_lists.deleted=0";
212
213                         $emailman->restricted_domains=array();
214                         $emailman->restricted_addresses=array();
215
216                         $result1=$db->query($plc_query);
217                         while($row1 = $db->fetchByAssoc($result1)){
218                                 if ($row1['list_type']=='exempt_domain') {
219                                         $emailman->restricted_domains[strtolower($row1['domain_name'])]=1;
220                                 } else {
221                                     //find email address of targets in this prospect list.
222                                         $email_query = "SELECT email_address FROM email_addresses ea JOIN email_addr_bean_rel eabr ON ea.id = eabr.email_address_id JOIN prospect_lists_prospects plp ON eabr.bean_id = plp.related_id AND eabr.bean_module = plp.related_type AND plp.prospect_list_id = '{$row1['prospect_list_id']}' and plp.deleted = 0";
223                                         $email_query_result=$db->query($email_query);
224
225                                         while($email_address = $db->fetchByAssoc($email_query_result)){
226                                                 //ignore empty email addresses;
227                                                 if (!empty($email_address['email_address'])) {
228                             $emailman->restricted_addresses[strtolower($email_address['email_address'])]=1;
229                                                 }
230                                         }
231                                 }
232                         }
233                 }
234
235                 if(!$emailman->sendEmail($mail,$massemailer_email_copy,$test)){
236                         $GLOBALS['log']->fatal("Email delivery FAILURE:" . print_r($row,true));
237                 } else {
238                         $GLOBALS['log']->debug("Email delivery SUCCESS:" . print_r($row,true));
239                 }
240                 if($mail->isError()){
241                         $GLOBALS['log']->fatal("Email delivery error:" . print_r($row,true). $mail->ErrorInfo);
242                 }
243         }
244
245         $send_all=$send_all?!$no_items_in_queue:$send_all;
246
247 }while ($send_all == true);
248
249 if ($admin->settings['mail_sendtype'] == "SMTP") {
250         $mail->SMTPClose();
251 }
252 if(isset($temp_user)){
253         $current_user = $temp_user;
254 }
255 if (isset($_REQUEST['return_module']) && isset($_REQUEST['return_action']) && isset($_REQUEST['return_id'])) {
256     $from_wiz=' ';
257     if(isset($_REQUEST['from_wiz'])&& $_REQUEST['from_wiz']==true){
258         header("Location: index.php?module={$_REQUEST['return_module']}&action={$_REQUEST['return_action']}&record={$_REQUEST['return_id']}&from=test");
259     }else{
260                 header("Location: index.php?module={$_REQUEST['return_module']}&action={$_REQUEST['return_action']}&record={$_REQUEST['return_id']}");
261     }
262 } else {
263         /* this will be triggered when manually sending off Email campaigns from the
264          * Mass Email Queue Manager.
265         */
266         if(isset($_POST['manual'])) {
267                 header("Location: index.php?module=EmailMan&action=index");
268         }
269 }
270 ?>