Changeset 987


Ignore:
Timestamp:
01/20/09 02:39:25 (3 years ago)
Author:
strat.cristian@…
Message:

HTML Newsletter

This patch adds support for HTML in the infoarena newsletter. A newsletter can be created just like a regular wiki page, using textile, macros, and templates. Sending is still done with a command-line script.

Location:
trunk
Files:
11 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/common/db/textblock.php

    r981 r987  
    7272function textblock_complex_query($options) 
    7373{ 
    74     //log_print_r($options); 
     74    // log_print_r($options); 
    7575 
    7676    $field_list = "`name`, `title`, `creation_timestamp`, `timestamp`, `security`, `user_id`, `forum_topic`"; 
     
    112112                          $where, $where, $order, $options['limit_start'], $options['limit_count']); 
    113113    } else { 
    114         $query = "SELECT $field_list FROM ia_textblock $join $where"; 
    115     } 
    116     //log_print("QUERY: " . $query); 
     114        $query = "SELECT $field_list FROM ia_textblock 
     115                  $join $where ORDER BY ia_textblock.`creation_timestamp` $order"; 
     116    } 
     117    // log_print("QUERY: " . $query); 
    117118    return db_fetch_all($query); 
    118119} 
     
    166167// Get all textblocks(without content) with a certain prefix). 
    167168// Ordered by name. 
    168 function textblock_get_by_prefix($prefix, $content = false, $username = false) { 
     169function textblock_get_by_prefix($prefix, $content = false, $username = false, 
     170        $order = 'asc') { 
    169171    return textblock_complex_query(array( 
    170172            'content' => $content, 
    171173            'username' => $username, 
    172174            'prefix' => $prefix, 
     175            'order' => $order, 
    173176    )); 
    174177} 
  • trunk/config.php.sample

    r983 r987  
    8383define("IA_TASK_TEXTBLOCK_PREFIX", 'problema/'); 
    8484define("IA_USER_TEXTBLOCK_PREFIX", 'utilizator/'); 
     85define("IA_NEWSLETTER_TEXTBLOCK_PREFIX", 'newsletter/'); 
    8586// FIXME: Do we really need this? 
    8687define("IA_ROUND_TEXTBLOCK_PREFIX", 'runda/'); 
  • trunk/scripts/send-newsletter

    r945 r987  
    22<?php 
    33 
    4 // dependencies 
    54require_once(dirname($argv[0]) . "/utilities.php"); 
     5require_once(IA_ROOT_DIR . 'common/external_libs/class.phpmailer.php'); 
    66require_once(IA_ROOT_DIR."common/db/user.php"); 
    77require_once(IA_ROOT_DIR."common/db/textblock.php"); 
     
    99require_once(IA_ROOT_DIR."common/rating.php"); 
    1010require_once(IA_ROOT_DIR."common/email.php"); 
     11require_once(IA_ROOT_DIR."common/newsletter.php"); 
    1112require_once(IA_ROOT_DIR."www/url.php"); 
    1213db_connect(); 
    1314 
    14 // config 
    15 define("IA_NEWSLETTER_FROM", "Cristian George Strat <cristian@infoarena.ro>"); 
    16 // define("IA_NEWSLETTER_FROM", "Crestez Dan Leonard <cdleonard@gmail.com>"); 
     15// Configuration section. 
     16 
     17define("IA_NEWSLETTER_FROM", "cristian@infoarena.ro"); 
     18define("IA_NEWSLETTER_FROM_NAME", "Cristian George Strat"); 
    1719// how many emails to send at once (with no delay) 
    1820define("IA_BURST_LENGTH", 25); 
    1921// pause (milliseconds i.e. 10^-3) between bursts. 
    2022define("IA_BURST_DELAY", 500); 
    21  
    2223// place where we store newsletter logs 
    2324define("IA_NEWSLETTER_LOGDIR", IA_ROOT_DIR."scripts/newsletter-logs/"); 
     25// application to use for previewing the HTML newsletter 
     26define("IA_NEWSLETTER_PREVIEW_APP", "elinks"); 
     27 
     28// Create PHPMailer object from newsletter textblock, and for given recipient. 
     29function phpmail_create($textblock, $recipient) { 
     30    log_assert_valid(user_validate($recipient)); 
     31    log_assert_valid(textblock_validate($textblock)); 
     32    $phpmail = new PHPMailer(); 
     33    phpmail_config($phpmail); 
     34    $phpmail->Subject = newsletter_subject($textblock, $recipient); 
     35    $phpmail->AltBody = newsletter_body_alternate($textblock, $recipient); 
     36    $phpmail->Body = newsletter_body_html($textblock, $recipient); 
     37    $phpmail->AddAddress($recipient['email'], $recipient['full_name']); 
     38    return $phpmail; 
     39} 
     40 
     41// Configure a PHPMailer object. 
     42function phpmail_config(&$phpmail) { 
     43    if (IA_SMTP_ENABLED) { 
     44        $phpmail->IsSMTP(); 
     45        $phpmail->Host = IA_SMTP_HOST; 
     46        $phpmail->Port = IA_SMTP_PORT; 
     47    } else { 
     48        // Use PHP mail(...) function. 
     49        $phpmail->IsMail(); 
     50    } 
     51    $phpmail->From = IA_NEWSLETTER_FROM; 
     52    $phpmail->FromName = IA_NEWSLETTER_FROM_NAME; 
     53    $phpmail->CharSet = "UTF-8"; 
     54} 
    2455 
    2556// return array with valid subscriber list identifiers 
     
    5283            return db_fetch_all($query); 
    5384 
    54         case 'test': 
    55             // a small set of users. meant for testing 
    56             $usernames = array('wickedman', 'fluffy', 'domino', 'silviug', 
    57                                'Cosmin', 'wick3dman'); 
     85        case 'review': 
     86            // a small set of users. meant for reviewing 
     87            $usernames = array('wickedman', 'domino', 'silviug', 'Cosmin'); 
    5888            $query = "SELECT * FROM ia_user 
    5989                      WHERE username IN ('".join("', '", $usernames)."') 
     
    6191            return db_fetch_all($query); 
    6292 
    63         case 'tinytest': 
    64             $usernames = array('wickedman', 'wick3dman'); 
     93        case 'test': 
     94            // test the newsletter in various email clients 
     95            $usernames = array('gmail_test', 'yahoo_test', 'hotmail_test', 
     96                    'k_test'); 
    6597            $query = "SELECT * FROM ia_user 
    6698                      WHERE username IN ('".join("', '", $usernames)."') 
     
    75107// Preview email for a given recipient 
    76108// When recipient is null, no tags are replaced 
    77 function preview_email($textblock, $recipient = null, $short = false) { 
    78     log_assert(is_null($recipient) || valid_recipient($recipient)); 
    79  
    80     if ($recipient) { 
    81         $subject = email_tags($textblock['title'], $recipient); 
    82         $body = email_tags($textblock['text'], $recipient); 
    83     } 
    84     else { 
    85         $subject = $textblock['title']; 
    86         $body = $textblock['text']; 
    87     } 
     109function preview_email($textblock, $recipient, $use_external_app = true) { 
     110    log_assert_valid(user_validate($recipient)); 
     111    log_assert_valid(textblock_validate($textblock)); 
     112    $phpmail = phpmail_create($textblock, $recipient); 
     113    $temp_filename = tempnam(sys_get_temp_dir(), 'ia-newsletter-preview-'); 
     114    file_put_contents($temp_filename, $phpmail->Body); 
    88115 
    89116    echo "\n\n===  e-mail ========================================\n"; 
    90     echo "From   : ".IA_NEWSLETTER_FROM."\n"; 
     117    echo "From   : {$phpmail->From}\n"; 
    91118    if ($recipient) { 
    92119        echo "To     : ".$recipient['email']."\n"; 
    93120    } 
    94     else { 
    95         echo "To     : %email%\n"; 
    96     } 
    97     echo "Subject: {$subject}\n"; 
    98     if (!$short) { 
    99         echo "---  body ------------------------------------------\n"; 
    100         echo wordwrap($body, IA_EMAIL_WORDRAP)."\n"; 
    101         echo "--- /body ------------------------------------------\n"; 
    102     } 
     121    echo "Subject: {$phpmail->Subject}\n"; 
     122    echo "---  alternate text --------------------------------\n"; 
     123    echo wordwrap($phpmail->AltBody, IA_EMAIL_WORDRAP)."\n"; 
     124    echo "--- /alternate text --------------------------------\n"; 
    103125    echo "=== /e-mail ========================================\n\n"; 
    104126 
    105127    // warn users if word-wrapping is needed 
    106     if (wordwrap($body, IA_EMAIL_WORDRAP) != $body) { 
     128 
     129    if (wordwrap($phpmail->AltBody, IA_EMAIL_WORDRAP) != $phpmail->AltBody) { 
    107130        log_print("WARNING: Please word-wrap the text to ".IA_EMAIL_WORDRAP 
    108131                  ." characters per line!\n"); 
    109132    } 
    110 } 
    111  
    112 // Replace special email tags (placeholders) with real content 
    113 function email_tags($content, $recipient) { 
    114     log_assert(valid_recipient($recipient)); 
    115  
    116     global $_et_callback_hack; 
    117     $_et_callback_hack = $recipient; 
    118  
    119     $content = preg_replace_callback('/%([a-z_0-9]+)%/', 'email_tags_callback', 
    120                                      $content); 
    121  
    122     return $content; 
    123 } 
    124  
    125 // Callback for email_tags 
    126 function email_tags_callback($matches) { 
    127     global $_et_callback_hack; 
    128     log_assert(valid_recipient($_et_callback_hack)); 
    129     log_assert(2 == count($matches)); 
    130  
    131     $recipient = $_et_callback_hack; 
    132     $tag = $matches[1]; 
    133  
    134     switch ($tag) { 
    135         case 'rating': 
    136             if ($recipient['rating_cache']) { 
    137                 return rating_scale($recipient['rating_cache']); 
    138             } 
    139             else { 
    140                 return 'fara rating'; 
    141             } 
    142         case 'full_name': 
    143             return $recipient['full_name']; 
    144         case 'username': 
    145             return $recipient['username']; 
    146         case 'email': 
    147             return $recipient['email']; 
    148         case 'url_profile': 
    149             return url_user_profile($recipient['username'], true); 
    150         case 'url_infoarena': 
    151             return IA_URL; 
    152         case 'url_forum': 
    153             return IA_SMF_URL; 
    154         case 'url_unsubscribe': 
    155             // unsubscribe link 
    156             $key = user_unsubscribe_key($recipient); 
    157             return url_absolute(url_unsubscribe($recipient['username'], $key)); 
    158         case 'your_rating_is': 
    159             // nice sentence telling user what her rating is. 
    160             // when user is not rated, expand tag to nothing 
    161             if ((int)$recipient['rating_cache']) { 
    162                 return 'Rating-ul tau este ' 
    163                        .rating_scale($recipient['rating_cache']) 
    164                        .".\n"; 
    165             } 
    166             else { 
    167                 return ''; 
    168             } 
    169         default: 
    170             log_error("Invalid email tag: ".$tag); 
    171     } 
    172 } 
    173  
    174  
    175 // Make sure $recipient is a valid... recipient :) 
    176 // Keep these checks very light. Performance bottleneck ahead. 
    177 function valid_recipient($recipient) { 
    178     $valid = !is_null($recipient) && isset($recipient['username']); 
    179     if (!$valid) { 
    180         log_print("Invalid recipient: ".print_r($recipient, true)); 
    181     } 
    182     return $valid; 
     133 
     134    // display HTML body in preview app 
     135 
     136    if ($use_external_app) { 
     137        system(IA_NEWSLETTER_PREVIEW_APP." ".$temp_filename); 
     138        unlink($temp_filename); 
     139    } 
    183140} 
    184141 
    185142// Format recipient to display it nicely on screen / log 
    186143function recipient_str($recipient) { 
    187     log_assert(valid_recipient($recipient)); 
     144    log_assert_valid(user_validate($recipient)); 
    188145    return '<'.$recipient['email'].'> ['.$recipient['username'] 
    189146            .'] '.$recipient['full_name']; 
     
    245202 
    246203// small preview before entering main menu 
    247 preview_email($textblock, null, true); 
     204preview_email($textblock, newsletter_anonymous_user(), false); 
    248205 
    249206// check log 
     
    287244            } 
    288245            else { 
    289                 $user = null; 
     246                $user = newsletter_anonymous_user(); 
    290247            } 
    291248            preview_email($textblock, $user); 
     
    406363 
    407364                $i++; 
    408                 log_assert(valid_recipient($recipient)); 
     365                log_assert_valid(user_validate($recipient)); 
    409366 
    410367                // log invalid email addresses 
     
    430387 
    431388                // send email 
    432                 $subject = email_tags($textblock['title'], $recipient); 
    433                 $body = email_tags($textblock['text'], $recipient); 
    434                 $success = send_email($recipient['email'], $subject, $body, 
    435                                       IA_NEWSLETTER_FROM, IA_NEWSLETTER_FROM, 
    436                                       false); 
     389                $phpmail = phpmail_create($textblock, $recipient); 
     390                $success = $phpmail->Send(); 
    437391 
    438392                if ($success) { 
    439393                    log_putch('.'); 
    440                     nlog($newsletter_id, 
    441                          $i."\tok\t".recipient_str($recipient)); 
     394                    nlog($newsletter_id, $i."\tok\t".recipient_str($recipient)); 
    442395                    $count_ok++; 
    443396                } 
    444397                else { 
    445398                    log_putch('e'); 
    446                     nlog($newsletter_id, 
    447                          $i."\tERROR\t".recipient_str($recipient)); 
     399                    nlog($newsletter_id, $i."\tERROR\t". 
     400                            recipient_str($recipient)."\t". 
     401                            $phpmail->ErrorInfo); 
    448402                    $count_error++; 
    449403                } 
  • trunk/www/controllers/textblock.php

    r968 r987  
    99// View a plain textblock. 
    1010// That textblock can be owned by something else. 
    11 function controller_textblock_view($page_name, $rev_num = null) { 
     11function controller_textblock_view($page_name, $rev_num = null, 
     12        $display_view = 'views/textblock_view.php') { 
    1213    global $identity_user; 
    1314 
     
    4950    $view['forum_topic'] = $page['forum_topic']; 
    5051 
    51     execute_view_die('views/textblock_view.php', $view); 
     52    execute_view_die($display_view, $view); 
    5253} 
    5354 
  • trunk/www/index.php

    r971 r987  
    5252                               'unsubscribe', 'resetpass', 'reeval' 
    5353)); 
     54 
    5455// 
    5556// Here comes the big url mapper. 
     
    226227} 
    227228 
     229// Newsletter index 
     230else if ($page == 'newsletter') { 
     231    require_once(IA_ROOT_DIR.'www/controllers/newsletter.php'); 
     232    controller_newsletter_index(); 
     233} 
     234 
     235// Display one newsletter. 
     236else if (IA_NEWSLETTER_TEXTBLOCK_PREFIX == $urlstart.'/' 
     237        && 'view' == $action) { 
     238    require_once(IA_ROOT_DIR.'www/controllers/newsletter.php'); 
     239    if ('body' == request('preview')) { 
     240        controller_newsletter_preview_body($page_id, request('revision')); 
     241    } else { 
     242        controller_newsletter_preview_frame($page_id, request('revision')); 
     243    } 
     244} 
     245 
    228246// general textblock view 
    229247else if ($action == 'view') { 
  • trunk/www/static/css/screen.css

    r980 r987  
    14771477} 
    14781478 
     1479/* newsletter preview */ 
     1480 
     1481#newsletter_preview { 
     1482    width: 95%; 
     1483    height: 600px; 
     1484    border: none; 
     1485} 
     1486 
  • trunk/www/url.php

    r962 r987  
    336336} 
    337337 
     338// Newsletter 
     339 
     340function url_newsletter($page_name, $rev = null) { 
     341    return url_textblock_revision($page_name, $rev); 
     342} 
     343 
     344function url_newsletter_preview_body($page_name, $rev = null) { 
     345    return url_complex($page_name, array('revision' => $rev, 
     346            'preview' => 'body')); 
     347} 
     348 
    338349?> 
Note: See TracChangeset for help on using the changeset viewer.