This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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-2013 SugarCRM Inc. |
||
6 | |||
7 | * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd. |
||
8 | * Copyright (C) 2011 - 2014 Salesagility Ltd. |
||
9 | * |
||
10 | * This program is free software; you can redistribute it and/or modify it under |
||
11 | * the terms of the GNU Affero General Public License version 3 as published by the |
||
12 | * Free Software Foundation with the addition of the following permission added |
||
13 | * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK |
||
14 | * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY |
||
15 | * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. |
||
16 | * |
||
17 | * This program is distributed in the hope that it will be useful, but WITHOUT |
||
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
||
19 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
||
20 | * details. |
||
21 | * |
||
22 | * You should have received a copy of the GNU Affero General Public License along with |
||
23 | * this program; if not, see http://www.gnu.org/licenses or write to the Free |
||
24 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
||
25 | * 02110-1301 USA. |
||
26 | * |
||
27 | * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, |
||
28 | * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected]. |
||
29 | * |
||
30 | * The interactive user interfaces in modified source and object code versions |
||
31 | * of this program must display Appropriate Legal Notices, as required under |
||
32 | * Section 5 of the GNU Affero General Public License version 3. |
||
33 | * |
||
34 | * In accordance with Section 7(b) of the GNU Affero General Public License version 3, |
||
35 | * these Appropriate Legal Notices must retain the display of the "Powered by |
||
36 | * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not |
||
37 | * reasonably feasible for technical reasons, the Appropriate Legal Notices must |
||
38 | * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". |
||
39 | ********************************************************************************/ |
||
40 | |||
41 | /********************************************************************************* |
||
42 | |||
43 | * Description: |
||
44 | ********************************************************************************/ |
||
45 | //find all mailboxes of type bounce. |
||
46 | |||
47 | /** |
||
48 | * Retrieve the attached error report for a bounced email if it exists. |
||
49 | * |
||
50 | * @param Email $email |
||
51 | * @return string |
||
52 | */ |
||
53 | function retrieveErrorReportAttachment($email) |
||
54 | { |
||
55 | $contents = ""; |
||
56 | $query = "SELECT description FROM notes WHERE file_mime_type = 'messsage/rfc822' AND parent_type='Emails' AND parent_id = '".$email->id."' AND deleted=0"; |
||
57 | $rs = $GLOBALS['db']->query($query); |
||
58 | while ($row = $GLOBALS['db']->fetchByAssoc($rs)) |
||
59 | $contents .= $row['description']; |
||
60 | |||
61 | return $contents; |
||
62 | } |
||
63 | |||
64 | /** |
||
65 | * Create a bounced log campaign entry |
||
66 | * |
||
67 | * @param array $row |
||
68 | * @param Email $email |
||
69 | * @param string $email_description |
||
70 | * @return string |
||
71 | */ |
||
72 | function createBouncedCampaignLogEntry($row,$email, $email_description) |
||
73 | { |
||
74 | $GLOBALS['log']->debug("Creating bounced email campaign log"); |
||
75 | $bounce = new CampaignLog(); |
||
76 | $bounce->campaign_id=$row['campaign_id']; |
||
77 | $bounce->target_tracker_key=$row['target_tracker_key']; |
||
78 | $bounce->target_id= $row['target_id']; |
||
79 | $bounce->target_type=$row['target_type']; |
||
80 | $bounce->list_id=$row['list_id']; |
||
81 | $bounce->marketing_id=$row['marketing_id']; |
||
82 | |||
83 | $bounce->activity_date=$email->date_created; |
||
84 | $bounce->related_type='Emails'; |
||
85 | $bounce->related_id= $email->id; |
||
86 | |||
87 | //do we have the phrase permanent error in the email body. |
||
88 | if (preg_match('/permanent[ ]*error/',$email_description)) |
||
89 | { |
||
90 | $bounce->activity_type='invalid email'; |
||
91 | markEmailAddressInvalid($email); |
||
92 | } |
||
93 | else |
||
94 | $bounce->activity_type='send error'; |
||
95 | |||
96 | $return_id=$bounce->save(); |
||
97 | return $return_id; |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * Given an email address, mark it as invalid. |
||
102 | * |
||
103 | * @param $email_address |
||
104 | */ |
||
105 | function markEmailAddressInvalid($email_address) |
||
106 | { |
||
107 | if(empty($email_address)) |
||
108 | return; |
||
109 | $sea = new SugarEmailAddress(); |
||
110 | $rs = $sea->retrieve_by_string_fields( array('email_address_caps' => trim(strtoupper($email_address))) ); |
||
111 | if($rs != null) |
||
112 | { |
||
113 | $sea->AddUpdateEmailAddress($email_address, 1, 0, $rs->id); |
||
114 | } |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * Get the existing campaign log entry by tracker key. |
||
119 | * |
||
120 | * @param string Target Key |
||
121 | * @return array Campaign Log Row |
||
122 | */ |
||
123 | function getExistingCampaignLogEntry($identifier) |
||
124 | { |
||
125 | $row = FALSE; |
||
126 | $targeted = new CampaignLog(); |
||
127 | $where="campaign_log.activity_type='targeted' and campaign_log.target_tracker_key='{$identifier}'"; |
||
128 | $query=$targeted->create_new_list_query('',$where); |
||
129 | $result=$targeted->db->query($query); |
||
0 ignored issues
–
show
|
|||
130 | $row=$targeted->db->fetchByAssoc($result); |
||
131 | |||
132 | return $row; |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Scan the bounced email searching for a valid target identifier. |
||
137 | * |
||
138 | * @param string Email Description |
||
139 | * @return array Results including matches and identifier |
||
140 | */ |
||
141 | function checkBouncedEmailForIdentifier($email_description) |
||
142 | { |
||
143 | $matches = array(); |
||
144 | $identifiers = array(); |
||
145 | $found = FALSE; |
||
146 | //Check if the identifier is present in the header. |
||
147 | if(preg_match('/X-CampTrackID: [a-z0-9\-]*/',$email_description,$matches)) |
||
148 | { |
||
149 | $identifiers = preg_split('/X-CampTrackID: /',$matches[0],-1,PREG_SPLIT_NO_EMPTY); |
||
150 | $found = TRUE; |
||
151 | $GLOBALS['log']->debug("Found campaign identifier in header of email"); |
||
152 | } |
||
153 | else if( preg_match('/index.php\?entryPoint=removeme&identifier=[a-z0-9\-]*/',$email_description, $matches) ) |
||
154 | { |
||
155 | $identifiers = preg_split('/index.php\?entryPoint=removeme&identifier=/',$matches[0],-1,PREG_SPLIT_NO_EMPTY); |
||
156 | $found = TRUE; |
||
157 | $GLOBALS['log']->debug("Found campaign identifier in body of email"); |
||
158 | } |
||
159 | |||
160 | return array('found' => $found, 'matches' => $matches, 'identifiers' => $identifiers); |
||
161 | } |
||
162 | |||
163 | function campaign_process_bounced_emails(&$email, &$email_header) |
||
164 | { |
||
165 | global $sugar_config; |
||
166 | $emailFromAddress = $email_header->fromaddress; |
||
167 | $email_description = $email->raw_source; |
||
168 | |||
169 | //if raw_source is empty, try using the description instead |
||
170 | if (empty($email_description)){ |
||
171 | $email_description = $email->description; |
||
172 | } |
||
173 | |||
174 | $email_description .= retrieveErrorReportAttachment($email); |
||
175 | |||
176 | if (preg_match('/MAILER-DAEMON|POSTMASTER/i',$emailFromAddress)) |
||
177 | { |
||
178 | $email_description=quoted_printable_decode($email_description); |
||
179 | $matches=array(); |
||
180 | |||
181 | //do we have the identifier tag in the email? |
||
182 | $identifierScanResults = checkBouncedEmailForIdentifier($email_description); |
||
183 | |||
184 | if ( $identifierScanResults['found'] ) |
||
185 | { |
||
186 | $matches = $identifierScanResults['matches']; |
||
187 | $identifiers = $identifierScanResults['identifiers']; |
||
188 | |||
189 | if (!empty($identifiers)) |
||
190 | { |
||
191 | //array should have only one element in it. |
||
192 | $identifier = trim($identifiers[0]); |
||
193 | $row = getExistingCampaignLogEntry($identifier); |
||
194 | |||
195 | //Found entry |
||
196 | if (!empty($row)) |
||
197 | { |
||
198 | //do not create another campaign_log record is we already have an |
||
199 | //invalid email or send error entry for this tracker key. |
||
200 | $query_log = "select * from campaign_log where target_tracker_key='{$row['target_tracker_key']}'"; |
||
201 | $query_log .=" and (activity_type='invalid email' or activity_type='send error')"; |
||
202 | $targeted = new CampaignLog(); |
||
203 | $result_log=$targeted->db->query($query_log); |
||
204 | $row_log=$targeted->db->fetchByAssoc($result_log); |
||
205 | |||
206 | if (empty($row_log)) |
||
207 | { |
||
208 | $return_id = createBouncedCampaignLogEntry($row, $email, $email_description); |
||
209 | return TRUE; |
||
210 | } |
||
211 | else |
||
212 | { |
||
213 | $GLOBALS['log']->debug("Warning: campaign log entry already exists for identifier $identifier"); |
||
214 | return FALSE; |
||
215 | } |
||
216 | } |
||
217 | else |
||
218 | { |
||
219 | $GLOBALS['log']->info("Warning: skipping bounced email with this tracker_key(identifier) in the message body: ".$identifier); |
||
220 | return FALSE; |
||
221 | } |
||
222 | } |
||
223 | else |
||
224 | { |
||
225 | $GLOBALS['log']->info("Warning: Empty identifier for campaign log."); |
||
226 | return FALSE; |
||
227 | } |
||
228 | } |
||
229 | else |
||
230 | { |
||
231 | $GLOBALS['log']->info("Warning: skipping bounced email because it does not have the removeme link."); |
||
232 | return FALSE; |
||
233 | } |
||
234 | } |
||
235 | else |
||
236 | { |
||
237 | $GLOBALS['log']->info("Warning: skipping bounced email because the sender is not MAILER-DAEMON."); |
||
238 | return FALSE; |
||
239 | } |
||
240 | } |
||
241 | ?> |
||
242 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.