/[drupal]/contributions/sandbox/megagrunt/modules/enewsletter/enewsletter_send_receive.inc
ViewVC logotype

Contents of /contributions/sandbox/megagrunt/modules/enewsletter/enewsletter_send_receive.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.11 - (show annotations) (download) (as text)
Wed May 11 15:13:11 2005 UTC (4 years, 6 months ago) by MegaGrunt
Branch: MAIN
CVS Tags: HEAD
Changes since 1.10: +220 -161 lines
File MIME type: text/x-php
Re-factored email send out functions:
1 <?php
2
3 // $Id: enewsletter_send_receive.inc,v 1.1 2004/11/12 21:36:25 MegaGrunt Exp $
4
5 // Author: Robert Castelo
6 // Support: development@cortextcommunications.com
7 // Info: http://www.cortextcommunications.com/development/newsletter
8
9 //
10 // ********** SEND EMAIL *****************************
11 //
12
13
14 function enewsletter_process_newsletters($newsletters) {
15
16 // Get Administration settings
17 $configuration = enewsletter_get_configuration();
18 $unsent_count = $configuration['send_maximum'];
19 $site_name = variable_get('site_name', 'drupal');
20
21 // Loop through each email newsletter
22 foreach ($newsletters as $newsletter) {
23
24 // Check it's time to send this newsletter
25 // Publication time 0 means schedule is set to manual
26 if ($newsletter->next != 0 && $newsletter->next <= time()) {
27
28 if ($newsletter->last == 0) $newsletter->last = $newsletter->start;
29 if ($newsletter->first== 0) $newsletter->first = $newsletter->next;
30
31 // Get terms and nodes
32 $allowed_terms = enewsletter_get_allowed_terms($newsletter->enewsletter_id);
33 $selected_terms = enewsletter_get_selected_terms($newsletter->enewsletter_id);
34 // check only allowed terms are included
35 $selected_terms = enewsletter_check_terms($allowed_terms, $selected_terms);
36 $nodes_by_term = enewsletter_get_nodes($newsletter->enewsletter_id, $selected_terms, $newsletter->last, $newsletter->next);
37
38 // Get user info
39 $subscriptions = enewsletter_get_subscriptions_qued($newsletter->enewsletter_id, $newsletter->next, $unsent_count, $configuration['bounce_limit']);
40 $profiles = enewsletter_get_profiles($newsletter->enewsletter_id, $newsletter->next, $unsent_count, $configuration['bounce_limit']);
41 // LOCK
42
43 // Check if there are subscriptions
44 if ($subscriptions) {
45
46 // Get templates for this newsletter (plain text and HTML)
47 $templates = enewsletter_load_newsletter_templates($newsletter);
48 // Encode email subject line
49 //$subject = enewsletter_email_encode($newsletter->title);
50 $site_name = check_plain($site_name);
51 $newsletter->title = check_plain($newsletter->title);
52
53
54 // loop through subscriptions
55 while ($subscription = db_fetch_object($subscriptions)) {
56
57 // get nodes for this user
58 $nodes = enewsletter_load_subscription_nodes($selected_terms[$subscription->uid], $nodes_by_term, $subscription->format);
59
60 // if there are no nodes, don't send - unless it's an announcement
61 if ($nodes || $newsletter->enewsletter_id == ANNOUNCEMENT) {
62
63 // process nodes into one string
64 $nodes = enewsletter_process_nodes($nodes, $subscription->uid, $subscription->format);
65
66 // load template for this subscription
67 $template->template = ($subscription->format == 'html') ? $templates['html'] : $templates['text'];
68 $template->format = ($subscription->format == 'html') ? $templates['html_format'] : $templates['text_format'];
69
70 // load content for this subscription
71 $content = enewsletter_load_content($site_name, $newsletter, $template, $subscription, $nodes, $profiles[$subscription->uid]);
72 $header = enewsletter_email_header($configuration, $newsletter->enewsletter_id, $subscription->format, $subscription->mail);
73
74 // convert if subscription format is plain text
75 if ($subscription->format != 'html') {
76 $converted = html2txt_convert($content, 70, TRUE, '', 3);
77 $content = $converted->text;
78 $content .= $converted->links;
79 }
80
81 // Send email
82 enewsletter_send_email($subscription->mail, $newsletter->title, $content, $header);
83 usleep($configuration['send_delay']);
84
85 // make record of send
86 enewsletter_set_sent($newsletter->enewsletter_id, $subscription->uid, $newsletter->next);
87 $unsent_count = $unsent_count - 1;
88
89 // Check maximum number of emails (per cron) have not been sent
90 // UNLOCK
91 if ($unsent_count == 0) return;
92 }
93 }
94
95 }
96 // UNLOCK
97 enewsletter_set_next_publication_time($newsletter);
98 }
99 }
100
101 return;
102 }
103
104 function enewsletter_load_subscription_nodes($selected_terms, $nodes_by_term, $format) {
105
106 if (!is_array($selected_terms) || !is_array($nodes_by_term)) return;
107
108 while (list($term_id, $nodes) = each($nodes_by_term)) {
109
110 // check if this term was selected by user
111 if (in_array($term_id, $selected_terms)) {
112
113 foreach($nodes as $node) {
114
115 // check if node is in list already
116 if (!$nodes_list[$node->nid]) {
117 $nodes_list[$node->nid] = $node;
118 $nodes_list[$node->nid]->title = check_plain($node->title);
119 $nodes_list[$node->nid]->link_text = ($node->teaser != $node->body) ? t('Read More...') : t('Web page...');
120 $nodes_list[$node->nid]->teaser = check_output($node->teaser, $node->format);
121 }
122 }
123 }
124 }
125
126 return $nodes_list;
127 }
128
129
130 // Get list of users subscribed to this newsletter
131 function enewsletter_get_subscriptions_qued($newsletter_id, $time_of_publication, $max_ammount_emails, $bounce_limit) {
132
133 $subscriptions = db_query_range("
134 SELECT s.*, u.*, w.lid
135 FROM {enewsletter_subscriptions} s
136 LEFT JOIN {enewsletter_subscribers} w ON w.uid = s.uid
137 LEFT JOIN {users} u ON s.uid = u.uid
138 LEFT JOIN {enewsletter_bounce_count} b ON u.mail = b.email
139 LEFT JOIN {enewsletter_sent} m ON (m.uid = s.uid AND m.enewsletter_id = s.enewsletter_id AND m.pub_time = '%d')
140 WHERE s.enewsletter_id = '%d'
141 AND (b.bounces IS NULL OR b.bounces < '%d')
142 AND m.sent IS NULL
143 ORDER BY s.uid
144 ", $time_of_publication, $newsletter_id, $bounce_limit, 0, $max_ammount_emails);
145
146 return $subscriptions;
147 }
148
149
150 function enewsletter_get_profiles($newsletter_id, $time_of_publication, $max_ammount_emails, $bounce_limit) {
151
152 // check profiles enabled
153 $profiles_enabled = module_exist('profile');
154 if (!$profiles_enabled) return;
155
156
157 // get count of fields
158 $field_count = db_result(db_query("SELECT count(*) FROM {profile_fields}"));
159
160 // get profile data
161
162 $result = db_query_range("
163 SELECT f.name, f.type, v.value, s.uid
164 FROM {profile_values} v
165 LEFT JOIN {enewsletter_subscriptions} s ON s.uid = v.uid
166 LEFT JOIN {enewsletter_subscribers} w ON w.uid = s.uid
167 LEFT JOIN {users} u ON s.uid = u.uid
168 LEFT JOIN {enewsletter_bounce_count} b ON u.mail = b.email
169 LEFT JOIN {enewsletter_sent} m ON (m.uid = s.uid AND m.enewsletter_id = s.enewsletter_id AND m.pub_time = '%d')
170 INNER JOIN {profile_fields} f ON f.fid = v.fid
171 WHERE s.enewsletter_id = '%d'
172 AND (b.bounces IS NULL OR b.bounces < '%d')
173 AND m.sent IS NULL
174 ORDER BY s.uid
175 ", $time_of_publication, $newsletter_id, $bounce_limit, 0, $max_ammount_emails * $field_count);
176
177 while ($profile = db_fetch_object($result)) {
178 $profiles[$profile->uid][$profile->name] = _profile_field_serialize($profile->type) ? unserialize($profile->value) : $profile->value;
179 }
180
181 return $profiles;
182 }
183
184 function enewsletter_get_selected_terms($newsletter_id) {
185
186 $result = db_query("SELECT t.tid, t.uid FROM {enewsletter_selected} t WHERE t.enewsletter_id = '%d' ORDER BY t.uid", $newsletter_id);
187
188 while ($selected = db_fetch_object($result)) {
189 $selections[$selected->uid][] = $selected->tid;
190 }
191
192 return $selections;
193 }
194
195 function enewsletter_check_terms($allowed_terms, $selected_terms) {
196
197 if (!is_array($allowed_terms) || !is_array($selected_terms)) return;
198
199 while (list($uid, $terms) = each($selected_terms)) {
200
201 $cheked_terms[$uid] = array_intersect($terms, $allowed_terms);
202 }
203
204 return $cheked_terms;
205 }
206
207
208
209 // Get nodes to be used in email
210 function enewsletter_get_nodes($enewsletter_id, $terms, $start_date, $end_date) {
211
212 if (!$terms) return;
213
214 // Create list of terms
215 foreach ($terms as $term_array) {
216 foreach ($term_array as $term_id) {
217 $term_list[$term_id] = $term_id;
218 }
219 }
220
221 $number_of_terms = count($term_list);
222 $count = 0;
223
224 foreach($term_list as $term_id) {
225 $count ++;
226 $term_query .= "t.tid = '$term_id'";
227 if($count != $number_of_terms) $term_query .= ' OR ';
228 }
229
230 $node_results = db_query("
231 SELECT t.tid, n.nid, n.title, n.teaser, n.body, n.format
232 FROM {term_node} t
233 LEFT JOIN {node} n
234 ON t.nid = n.nid
235 RIGHT JOIN {enewsletter_nodes} e
236 ON e.nid = n.nid
237 WHERE (
238 ($term_query) AND
239 n.created > '%d' AND
240 n.created < '%d' AND
241 n.status = 1
242 )
243 ", $start_date, $end_date);
244
245 while ($node = db_fetch_object($node_results)) {
246 $nodes[$node->tid][$node->nid] = $node;
247 }
248
249 return $nodes;
250 }
251
252
253 function enewsletter_load_newsletter_templates($newsletter) {
254 $template_text = enewsletter_get_template($newsletter->template_text);
255 $template_html = enewsletter_get_template($newsletter->template_html);
256 $templates = array(
257 'text' => $template_text['template'],
258 'text_format' => $template_text['format'],
259 'html' => $template_html['template'],
260 'html_format' => $template_html['format']);
261 return $templates;
262 }
263
264
265 // Fill template with newsletter/user data
266 function enewsletter_load_content($site_name, $newsletter, $template, $subscription, $nodes = NULL, $profile = NULL) {
267
268 global $base_url;
269
270 // Profile info
271 if ($profile) {
272 while (list($field, $data) = each($profile)) {
273 $profile_variables .= '$' . $field . ' = \'' . addslashes($data) . '\';';
274 }
275 }
276
277 $update_link = url('enewsletters/' . $subscription->lid, NULL, NULL, TRUE);
278 $unsubscribe_link = url('enewsletters/' . $subscription->lid, NULL, NULL, TRUE);
279
280 // Load variables and values into string
281 $php_variables = '<?php ';
282 $php_variables .= '$site_url = \'' . $base_url . '\';';
283 $php_variables .= '$site_name = \'' . $site_name . '\';';
284 $$php_variables .= 'username = \'' . check_plain($subscription->name) . '\';';
285 $php_variables .= '$publication_title = \'' . $newsletter->title . '\';';
286 $php_variables .= '$nodes = \'' . addslashes($nodes) . '\';';
287 $php_variables .= '$update_link = \'' . $update_link . '\';';
288 $php_variables .= '$unsubscribe_link = \'' . $unsubscribe_link. '\';';
289 $php_variables .= $profile_variables;
290 $php_variables .= '?>';
291
292
293 $content = check_output($php_variables . $template->template, $template->format);
294 $content = str_replace('$nodes', $nodes, $content);
295 $content = str_replace('$username', $subscription->name, $content);
296 $content = str_replace('$publication_title', $newsletter->title, $content);
297 $content = str_replace('$site_url', $base_url, $content);
298 $content = str_replace('$site_name', $site_name, $content);
299 $content = str_replace('$update_link', $update_link, $content);
300 $content = str_replace('$unsubscribe_link', $unsubscribe_link, $content);
301
302 if ($profile) {
303 reset($profile);
304 while (list($field, $data) = each($profile)) {
305 $content = str_replace('$' . $field, $data, $content);
306 }
307 }
308
309 // TO DO
310 // Add "refer a friend" link
311
312 return $content;
313 }
314
315
316 // Compile all nodes for this email into one block and add to message
317 function enewsletter_process_nodes($nodes, $uid, $email_format) {
318
319 if (!$nodes) return;
320
321 foreach($nodes as $node) {
322
323 $output .= '<h2>' . $node->title . '</h2>';
324 $output .= $node->teaser;
325
326 if ($email_format == 'html') {
327
328 $output .= l($node->link_text, "node/$node->nid", NULL, NULL, NULL, TRUE, FALSE);
329
330 } else {
331
332 $output .= $node->link_text . '<br />';
333 $output .= url("node/$node->nid", NULL, NULL, TRUE) . '<br /><br />';
334
335 }
336 }
337
338 return $output;
339 }
340
341
342 function enewsletter_email_header($configuration, $newsletter_id, $format, $to) {
343
344 $header .= "From: " . $configuration["from_address"];
345 $header .= "\n";
346 $header .= "Reply-to: " . $configuration["reply_address"];
347 $header .= "\n";
348 if ($configuration["set_return_path"] == 1) $header .= "Return-path: " . $configuration["bounce_addresss"] . "\n";
349 $header .= "X-Mailer: Drupal";
350 $header .= "\n";
351 $header .= 'X-Newsletter: ' . $newsletter_id;
352 $header .= "\n";
353 $header .= 'X-MessageId: ' . (time() + rand(1, 32767));
354 $header .= "\n";
355 $header .= "X-Subscriber: " . $to;
356 $header .= "\n";
357 $header .= "X-Date: " . time();
358 $header .= "\n";
359 $header .= "Errors-to: " . $configuration["bounce_addresss"];
360 $header .= "\n";
361 if ($format == "html") {
362 $header .= 'MIME-Version: 1.0';
363 $header .= "\n";
364 $header .= 'Content-Type: text/html; charset=UTF-8; Content-transfer-encoding: 8Bit';
365 } else {
366 $header .= 'MIME-Version: 1.0';
367 $header .= "\n";
368 $header .= 'Content-Type: text/plain; charset=UTF-8; format=flowed Content-transfer-encoding: 8Bit';
369 }
370
371 return $header;
372 }
373
374
375 function enewsletter_send_email($to, $subject, $content, $header) {
376
377 if ( mail($to, $subject, $content, $header) ) {
378
379 } else {
380 drupal_set_message (t("Some emails could not be sent- see log for more detail."), 'error');
381 watchdog('warning', t('Email newsletter: problem sending to ') . $to . '. "' . $subject . '" ' . t('not sent'));
382 }
383
384 return;
385 }
386
387
388 function enewsletter_email_encode($string, $charset = "UTF-8") {
389 /*
390 ** Used to encodes mail headers that contain non US- ASCII
391 ** characters.
392 ** http://www.rfc-editor.org/rfc/rfc2047.txt
393 **
394 ** Notes:
395 ** - The chunks come in groupings of 4 bytes when using base64
396 ** encoded.
397 ** - trim() is used to ensure that no extra spacing is added by
398 ** chunk_split() or preg_replace().
399 ** - Using \n as the chunk separator may cause problems on some
400 ** systems and may have to be changed to \r\n or \r.
401 */
402 $chunk_size = 75 - 7 - strlen($charset);
403 $chunk_size -= $chunk_size % 4;
404 $string = trim(chunk_split(base64_encode($string), $chunk_size, "\n"));
405 $string = trim(preg_replace('/^(.*)$/m', " =?$charset?B?\\1?=", $string));
406 return $string;
407 }
408
409
410 // Set send status of this newsletter
411 // Unfinished -> set que to last user email was sent to
412 // Finished -> tidy up and set next publication time
413 function enewsletter_set_sent($newsletter_id, $uid, $publication_time) {
414
415 db_query("INSERT INTO {enewsletter_sent} (enewsletter_id, uid, pub_time, sent) VALUES ('%d', '%d', '%d', '%d')", $newsletter_id, $uid, $publication_time, time());
416
417 return;
418 }
419
420 function enewsletter_set_next_publication_time($newsletter) {
421
422 // next publication date already set
423 if ($newsletter->next > time()) return;
424
425 $next_publication_time = enewsletter_publication_time($newsletter->next, $newsletter->frequency, $newsletter->every);
426 db_query("UPDATE {enewsletter_newsletters} SET first = '%d', next = '%d', last = '%d' WHERE enewsletter_id = '%d'", $newsletter->first, $next_publication_time, $newsletter->next, $newsletter->enewsletter_id);
427
428 return;
429 }
430
431
432 // Set time for next scheduled send out
433 function enewsletter_publication_time($previous, $frequency, $every) {
434
435 if ($frequency == 'manual') return 0;
436
437 $previous = getdate ($previous);
438
439 switch ($frequency) {
440 case 'hour':
441 $publication_time = mktime ($previous['hours'] + $every, $previous['minutes'], $previous['seconds'], $previous['mon'], ($previous['mday']), $previous['year'], -1);
442 break;
443 case 'day':
444 $publication_time = mktime ($previous['hours'], $previous['minutes'], $previous['seconds'], $previous['mon'], ($previous['mday'] + $every), $previous['year'], -1);
445 break;
446 case 'month':
447 $publication_time = mktime ($previous['hours'], $previous['minutes'], $previous['seconds'], ($previous['mon'] + $every), $previous['mday'], $previous['year'], -1);
448 break;
449 default:
450 }
451
452 return $publication_time;
453 }
454
455
456
457
458 // ********** INCOMING EMAIL *****************************
459
460
461 function enewsletter_mailbox_connect($config) {
462
463 $config = enewsletter_get_configuration();
464
465 $connection = imap_open("{" . $config['bounce_mailbox_host'] . ":" . $config['bounce_port'] . "}INBOX", $config['bounce_mailbox_user'], $config['bounce_mailbox_password']);
466
467 if (!$connection) {
468 watchdog("warning", t("Cannot create connection to") . $config['bounce_mailbox_host'] . ": " . imap_last_error());
469 return;
470 }
471
472 return $connection;
473 }
474
475
476 function enewsletter_process_bounces($connection, $config, $counter) {
477
478 $header = imap_fetchheader($connection, $counter);
479 $headerinfo = imap_headerinfo($connection, $counter);
480 $body = imap_body ($connection, $counter);
481 imap_delete($connection, $headerinfo>Msgno);
482
483 // Identify message
484 preg_match ("/X-MessageId: (.*)/i", $body, $match);
485 if (is_array($match) && isset($match[1])) $message_id = trim($match[1]);
486 //if(is_int($message_id) == false) $message_id = 0;
487
488 // Identify user
489 preg_match ("/X-Subscriber: (.*)/i", $body, $match);
490 if (is_array($match) && isset($match[1])) $member = trim($match[1]);
491 if (preg_match ("/.*@.*/i", $member, $match)) {
492 $results = db_query("SELECT uid FROM {users} WHERE mail = '%s' LIMIT 1", $member);
493 $found_user= db_fetch_object($results);
494 $user = $found_user->uid;
495 }
496
497 // Identify email address message was sent to
498 preg_match ("/X-Subscriber: (.*)/i", $body, $match);
499 if (is_array($match) && isset($match[1])) $address = trim($match[1]);
500
501 // Identify newsletter
502 preg_match ("/X-Newsletter: (.*)/i", $body, $match);
503 if (is_array($match) && isset($match[1])) $newsletter_id = trim($match[1]);
504
505 // Identify Date
506 preg_match ("/X-Date: (.*)/i", $body, $match);
507 if (is_array($match) && isset($match[1])) $date = trim($match[1]);
508
509 // if message_id doesn't exist
510 if (!$message_id) {
511 // set unknown message
512 return;
513 }
514
515 $results = db_query("SELECT bid FROM {enewsletter_bounce_record} WHERE message_id = '%s' LIMIT 1", $message_id);
516 $found_message = db_result($results);
517
518 if ($found_message) {
519 return;
520 }
521
522 $bounce_id = enewsletter_record_bounces($message_id, $newsletter_id, $date, $user, $address);
523 enewsletter_store_bounce($bounce_id, $header, serialize($headerinfo), $body);
524
525 return;
526 }
527
528
529 function enewsletter_record_bounces($message_id, $newsletter_id, $date, $user, $address) {
530
531 db_query("INSERT INTO {enewsletter_bounce_record} (bid, message_id, newsletter_id, date, user_id, address) VALUES (NULL, '%d', '%d', '%d', '%d', '%s')", $message_id, $newsletter_id, $date, $user, $address);
532 $bounce_id = db_result(db_query("SELECT LAST_INSERT_ID()"));
533 $bounces = db_result(db_query("SELECT bounces FROM {enewsletter_bounce_count} WHERE email = '%s'", $address));
534 if ($bounces == NULL) {
535 db_query("INSERT INTO {enewsletter_bounce_count} (email, bounces) VALUES ('%s', '1')", $address);
536 } else {
537 db_query("UPDATE {enewsletter_bounce_count} SET bounces = '%d' WHERE email = '%s'", $bounces + 1, $address);
538 }
539
540 return $bounce_id;
541 }
542
543
544 ?>

  ViewVC Help
Powered by ViewVC 1.1.2