示例#1
0
function repeatMessage($msgid)
{
    #  if (!USE_REPETITION && !USE_rss) return;
    $data = loadMessageData($msgid);
    ## do not repeat when it has already been done
    if ($data['repeatinterval'] == 0 || !empty($data['repeatedid'])) {
        return;
    }
    # calculate the future embargo, a multiple of repeatinterval minutes after the current embargo
    $msgdata = Sql_Fetch_Array_Query(sprintf('SELECT *,
        embargo +
            INTERVAL (FLOOR(TIMESTAMPDIFF(MINUTE, embargo, GREATEST(embargo, NOW())) / repeatinterval) + 1) * repeatinterval MINUTE AS newembargo
        FROM %s
        WHERE id = %d AND now() < repeatuntil', $GLOBALS['tables']['message'], $msgid));
    if (!$msgdata) {
        logEvent("Message {$msgid} not repeated due to reaching the repeatuntil date");
        return;
    }
    # check whether the new embargo is not on an exclusion
    if (isset($GLOBALS['repeat_exclude']) && is_array($GLOBALS['repeat_exclude'])) {
        $loopcnt = 0;
        while (excludedDateForRepetition($msgdata['newembargo'])) {
            if (++$loopcnt > 15) {
                logEvent("Unable to find new embargo date too many exclusions? for message {$msgid}");
                return;
            }
            $result = Sql_Fetch_Array_Query(sprintf("SELECT '%s' + INTERVAL repeatinterval MINUTE AS newembargo\n            FROM %s\n            WHERE id = %d", $msgdata['newembargo'], $GLOBALS['tables']['message'], $msgid));
            $msgdata['newembargo'] = $result['newembargo'];
        }
    }
    # copy the new message
    Sql_Query(sprintf('
    insert into %s (entered) values(now())', $GLOBALS['tables']['message']));
    $newid = Sql_Insert_id();
    require dirname(__FILE__) . '/structure.php';
    if (!is_array($DBstruct['message'])) {
        logEvent("Error including structure when trying to duplicate message {$msgid}");
        return;
    }
    foreach ($DBstruct['message'] as $column => $rec) {
        if ($column != 'id' && $column != 'entered' && $column != 'sendstart') {
            Sql_Query(sprintf('update %s set %s = "%s" where id = %d', $GLOBALS['tables']['message'], $column, addslashes($msgdata[$column]), $newid));
        }
    }
    $req = Sql_Query(sprintf("SELECT *\n    FROM %s\n    WHERE id = %d AND name NOT IN ('id')", $GLOBALS['tables']['messagedata'], $msgid));
    while ($row = Sql_Fetch_Array($req)) {
        setMessageData($newid, $row['name'], $row['data']);
    }
    Sql_Query(sprintf('update %s set embargo = "%s",status = "submitted",sent = "" where id = %d', $GLOBALS['tables']['message'], $msgdata['newembargo'], $newid));
    list($e['year'], $e['month'], $e['day'], $e['hour'], $e['minute'], $e['second']) = sscanf($msgdata['newembargo'], '%04d-%02d-%02d %02d:%02d:%02d');
    unset($e['second']);
    setMessageData($newid, 'embargo', $e);
    foreach (array('processed', 'astext', 'ashtml', 'astextandhtml', 'aspdf', 'astextandpdf', 'viewed', 'bouncecount') as $item) {
        Sql_Query(sprintf('update %s set %s = 0 where id = %d', $GLOBALS['tables']['message'], $item, $newid));
    }
    # lists
    $req = Sql_Query(sprintf('select listid from %s where messageid = %d', $GLOBALS['tables']['listmessage'], $msgid));
    while ($row = Sql_Fetch_Row($req)) {
        Sql_Query(sprintf('insert into %s (messageid,listid,entered) values(%d,%d,now())', $GLOBALS['tables']['listmessage'], $newid, $row[0]));
    }
    # attachments
    $req = Sql_Query(sprintf('select * from %s,%s where %s.messageid = %d and %s.attachmentid = %s.id', $GLOBALS['tables']['message_attachment'], $GLOBALS['tables']['attachment'], $GLOBALS['tables']['message_attachment'], $msgid, $GLOBALS['tables']['message_attachment'], $GLOBALS['tables']['attachment']));
    while ($row = Sql_Fetch_Array($req)) {
        if (is_file($row['remotefile'])) {
            # if the "remote file" is actually local, we want to refresh the attachment, so we set
            # filename to nothing
            $row['filename'] = '';
        }
        Sql_Query(sprintf('insert into %s (filename,remotefile,mimetype,description,size)
      values("%s","%s","%s","%s",%d)', $GLOBALS['tables']['attachment'], addslashes($row['filename']), addslashes($row['remotefile']), addslashes($row['mimetype']), addslashes($row['description']), $row['size']));
        $attid = Sql_Insert_id();
        Sql_Query(sprintf('insert into %s (messageid,attachmentid) values(%d,%d)', $GLOBALS['tables']['message_attachment'], $newid, $attid));
    }
    logEvent("Message {$msgid} was successfully rescheduled as message {$newid}");
    ## remember we duplicated, in order to avoid doing it again (eg when requeuing)
    setMessageData($msgid, 'repeatedid', $newid);
    if (getConfig('pqchoice') == 'phplistdotcom') {
        activateRemoteQueue();
    }
}
示例#2
0
if (!isset($_SESSION['fckeditor_height'])) {
    $_SESSION['fckeditor_height'] = getConfig('fckeditor_height');
}
#actions and store in database#######################
if ($send || $sendtest || $prepare || $save || $savedraft) {
    if ($savedraft || $save || $sendtest) {
        // We're just saving, not sending.
        if (!isset($messagedata['status']) || $messagedata['status'] == '') {
            // No status - move to draft state
            $messagedata['status'] = 'draft';
        }
    } elseif ($send) {
        // We're sending - change state to "send-it" status!
        if (is_array($messagedata['targetlist']) && count($messagedata['targetlist']) && !empty($messagedata['subject']) && !empty($messagedata['fromfield']) && !empty($messagedata['message']) && empty($duplicate_attribute)) {
            $messagedata['status'] = 'submitted';
            setMessageData($id, 'status', 'submitted');
        } else {
            if (USE_PREPARE) {
                $messagedata['status'] = 'prepared';
            } else {
                $messagedata['status'] = 'draft';
            }
        }
    }
    ### allow plugins manipulate data or save it somewhere else
    $plugintabs = array();
    foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
        #  print "Saving ".$plugin->name;
        $resultMsg = $plugin->sendMessageTabSave($id, $messagedata);
    }
    if (!$htmlformatted && strip_tags($messagedata['message']) != $messagedata['message']) {
示例#3
0
     if ($counters['sent'] > 0) {
         $msgperhour = 3600 / $totaltime * $counters['sent'];
         $secpermsg = $totaltime / $counters['sent'];
         $timeleft = ($counters['total_users_for_message ' . $messageid] - $counters['sent']) * $secpermsg;
         $eta = date('D j M H:i', time() + $timeleft);
     } else {
         $msgperhour = 0;
         $secpermsg = 0;
         $timeleft = 0;
         $eta = $GLOBALS['I18N']->get('unknown');
     }
     setMessageData($messageid, 'ETA', $eta);
     setMessageData($messageid, 'msg/hr', "{$msgperhour}");
     cl_progress('sent ' . $counters['sent'] . ' ETA ' . $eta . ' sending ' . sprintf('%d', $msgperhour) . ' msg/hr');
     setMessageData($messageid, 'to process', $counters['total_users_for_message ' . $messageid] - $counters['sent']);
     setMessageData($messageid, 'last msg sent', time());
     #  setMessageData($messageid,'totaltime',$GLOBALS['processqueue_timer']->elapsed(1));
     if (!empty($getspeedstats)) {
         processQueueOutput('end process user ' . "\n" . '-----------------------------------' . "\n" . $userid);
     }
 }
 $processed = $notsent + $counters['sent'] + $counters['invalid'] + $unconfirmed + $cannotsend + $counters['failed_sent'];
 processQueueOutput(s('Processed %d out of %d subscribers', $counters['processed_users_for_message ' . $messageid], $counters['total_users_for_message ' . $messageid]), 1, 'progress');
 if ($counters['total_users_for_message ' . $messageid] - $counters['sent_users_for_message ' . $messageid] <= 0 || $stopSending) {
     # this message is done
     if (!$someusers) {
         processQueueOutput($GLOBALS['I18N']->get('Hmmm, No users found to send to'), 1, 'progress');
     }
     if (!$counters['failed_sent']) {
         repeatMessage($messageid);
         $status = Sql_query(sprintf('update %s set status = "sent",sent = now() where id = %d', $GLOBALS['tables']['message'], $messageid));
         output('AR' . $affrows . ' N ' . $num_users . ' P' . $processed . ' S' . $sent . ' N' . $notsent . ' I' . $invalid . ' U' . $unconfirmed . ' C' . $cannotsend . ' F' . $failed_sent);
         $rn = $reload * $num_per_batch;
         output('P ' . $processed . ' N' . $num_users . ' NB' . $num_per_batch . ' BT' . $batch_total . ' R' . $reload . ' RN' . $rn);
     }
     $totaltime = $GLOBALS['processqueue_timer']->elapsed(1);
     $msgperhour = 3600 / $totaltime * $sent;
     if ($sent) {
         $secpermsg = $totaltime / $sent;
     } else {
         $secpermsg = 0;
     }
     $timeleft = ($num_users - $sent) * $secpermsg;
     $eta = date('D j M H:i', time() + $timeleft);
     setMessageData($messageid, 'ETA', $eta);
     setMessageData($messageid, 'msg/hr', $msgperhour);
     setMessageData($messageid, 'to process', $num_users - $sent);
 }
 $processed = $notsent + $sent + $invalid + $unconfirmed + $cannotsend + $failed_sent;
 output($GLOBALS['I18N']->get('Processed') . ' ' . $processed . ' ' . $GLOBALS['I18N']->get('out of') . ' ' . $num_users . ' ' . $GLOBALS['I18N']->get('users'));
 if ($num_users - $sent <= 0) {
     # this message is done
     if (!$someusers) {
         output($GLOBALS['I18N']->get('Hmmm, No users found to send to'));
     }
     if (!$failed_sent) {
         repeatMessage($messageid);
         $status = Sql_query(sprintf('update %s set status = "sent",sent = now() where id = %d', $GLOBALS['tables']['message'], $messageid));
         if (!empty($msgdata['notify_end']) && !isset($msgdata['end_notified'])) {
             $notifications = explode(',', $msgdata['notify_end']);
             foreach ($notifications as $notification) {
                 sendMail($notification, $GLOBALS['I18N']->get('Message Sending has finished'), sprintf($GLOBALS['I18N']->get('phplist has finished sending the message with subject %s'), $message['subject']));
示例#5
0
## checkboxes cannot be detected when unchecked, so they need registering in the "cb" array
## to be identified as listed, but not checked
## find the "cb" array and uncheck all checkboxes in it
## then the processing below will re-check them, if they were
if (isset($_REQUEST['cb']) && is_array($_REQUEST['cb'])) {
    foreach ($_REQUEST['cb'] as $cbname => $cbval) {
        ## $cbval is a dummy
        setMessageData($id, $cbname, '0');
    }
}
## remember all data entered
foreach ($_REQUEST as $key => $val) {
    /*
      print $key .' '.$val;
    */
    setMessageData($id, $key, $val);
    if (get_magic_quotes_gpc()) {
        if (is_string($val)) {
            $messagedata[$key] = stripslashes($val);
        } else {
            $messagedata[$key] = $val;
        }
    } else {
        $messagedata[$key] = $val;
    }
}
unset($GLOBALS['MD']);
$messagedata = loadMessageData($id);
/*
if (!empty($_REQUEST["criteria_attribute"])) {
  include dirname(__FILE__).'/addcriterion.php';
示例#6
0
function sendEmail($messageid, $email, $hash, $htmlpref = 0, $rssitems = array(), $forwardedby = array())
{
    $getspeedstats = VERBOSE && !empty($GLOBALS['getspeedstats']) && isset($GLOBALS['processqueue_timer']);
    $sqlCountStart = $GLOBALS['pagestats']['number_of_queries'];
    $isTestMail = isset($_GET['page']) && $_GET['page'] == 'send';
    ## for testing concurrency, put in a delay to check if multiple send processes cause duplicates
    #usleep(rand(0,10) * 1000000);
    global $strThisLink, $strUnsubscribe, $PoweredByImage, $PoweredByText, $cached, $website, $counters;
    if ($email == '') {
        return 0;
    }
    if ($getspeedstats) {
        output('sendEmail start ' . $GLOBALS['processqueue_timer']->interval(1));
    }
    #0013076: different content when forwarding 'to a friend'
    if (FORWARD_ALTERNATIVE_CONTENT) {
        $forwardContent = count($forwardedby) > 0;
    } else {
        $forwardContent = 0;
    }
    if (empty($cached[$messageid])) {
        if (!precacheMessage($messageid, $forwardContent)) {
            unset($cached[$messageid]);
            logEvent('Error loading message ' . $messageid . '  in cache');
            return 0;
        }
    } else {
        #  dbg("Using cached {$cached[$messageid]["fromemail"]}");
        if (VERBOSE) {
            output('Using cached message');
        }
    }
    if (VERBOSE) {
        output(s('Sending message %d with subject %s to %s', $messageid, $cached[$messageid]['subject'], $email));
    }
    ## at this stage we don't know whether the content is HTML or text, it's just content
    $content = $cached[$messageid]['content'];
    if (VERBOSE && $getspeedstats) {
        output('Load user start');
    }
    $userdata = array();
    $user_att_values = array();
    #0011857: forward to friend, retain attributes
    if ($hash == 'forwarded' && defined('KEEPFORWARDERATTRIBUTES') && KEEPFORWARDERATTRIBUTES) {
        $user_att_values = getUserAttributeValues($forwardedby['email']);
    } elseif ($hash != 'forwarded') {
        $user_att_values = getUserAttributeValues($email);
    }
    if (!is_array($user_att_values)) {
        $user_att_values = array();
    }
    foreach ($user_att_values as $key => $val) {
        $newkey = cleanAttributeName($key);
        ## in the help, we only list attributes with "strlen <= 30"
        unset($user_att_values[$key]);
        if (strlen($key) <= 30) {
            $user_att_values[$newkey] = $val;
        }
    }
    # print '<pre>';var_dump($user_att_values);print '</pre>';exit;
    $query = sprintf('select * from %s where email = "%s"', $GLOBALS['tables']['user'], sql_escape($email));
    $userdata = Sql_Fetch_Assoc_Query($query);
    if (empty($userdata['id'])) {
        $userdata = array();
    }
    #var_dump($userdata);
    if (stripos($content, '[LISTS]') !== false) {
        $listsarr = array();
        $req = Sql_Query(sprintf('select list.name,list.active from %s as list,%s as listuser where list.id = listuser.listid and listuser.userid = %d', $GLOBALS['tables']['list'], $GLOBALS['tables']['listuser'], $userdata['id']));
        while ($row = Sql_Fetch_Assoc($req)) {
            if ($row['active'] || PREFERENCEPAGE_SHOW_PRIVATE_LISTS) {
                array_push($listsarr, stripslashes($row['name']));
            }
        }
        if (!empty($listsarr)) {
            $html['lists'] = implode('<br/>', $listsarr);
            $text['lists'] = implode("\n", $listsarr);
        } else {
            $html['lists'] = $GLOBALS['strNoListsFound'];
            $text['lists'] = $GLOBALS['strNoListsFound'];
        }
        unset($listsarr);
    }
    if (VERBOSE && $getspeedstats) {
        output('Load user end');
    }
    if ($cached[$messageid]['userspecific_url']) {
        if (VERBOSE && $getspeedstats) {
            output('fetch personal URL start');
        }
        ## Fetch external content, only if the URL has placeholders
        if ($GLOBALS['can_fetchUrl'] && preg_match("/\\[URL:([^\\s]+)\\]/i", $content, $regs)) {
            while (isset($regs[1]) && strlen($regs[1])) {
                $url = $regs[1];
                if (!preg_match('/^http/i', $url)) {
                    $url = 'http://' . $url;
                }
                $remote_content = fetchUrl($url, $userdata);
                # @@ don't use this
                #      $remote_content = includeStyles($remote_content);
                if ($remote_content) {
                    ## @TODO, work out a nice way to do this: ##17197
                    ## collecting different remote URLS only works if they do not have html and body tags.
                    ## but if we strip them here, that might affect specially crafted ones, eg <body class="xx">
                    if (0) {
                        $remote_content = preg_replace('/<html[^>]*>/', '', $remote_content);
                        $remote_content = preg_replace('/<body[^>]*>/', '', $remote_content);
                        $remote_content = preg_replace('/<\\/html[^>]*>/', '', $remote_content);
                        $remote_content = preg_replace('/<\\/body[^>]*>/', '', $remote_content);
                    }
                    $content = str_replace($regs[0], '<!--' . $url . '-->' . $remote_content, $content);
                    $cached[$messageid]['htmlformatted'] = strip_tags($content) != $content;
                } else {
                    logEvent("Error fetching URL: {$regs['1']} to send to {$email}");
                    return 0;
                }
                preg_match("/\\[URL:([^\\s]+)\\]/i", $content, $regs);
            }
        }
        if (VERBOSE && $getspeedstats) {
            output('fetch personal URL end');
        }
    }
    if (VERBOSE && $getspeedstats) {
        output('define placeholders start');
    }
    $url = getConfig('unsubscribeurl');
    ## https://mantis.phplist.com/view.php?id=16680 -> the "sep" should be & for the text links
    $sep = strpos($url, '?') === false ? '?' : '&';
    $html['unsubscribe'] = sprintf('<a href="%s%suid=%s">%s</a>', $url, htmlspecialchars($sep), $hash, $strUnsubscribe);
    $text['unsubscribe'] = sprintf('%s%suid=%s', $url, $sep, $hash);
    $text['jumpoff'] = sprintf('%s%suid=%s&jo=1', $url, $sep, $hash);
    $html['unsubscribeurl'] = sprintf('%s%suid=%s', $url, htmlspecialchars($sep), $hash);
    $text['unsubscribeurl'] = sprintf('%s%suid=%s', $url, $sep, $hash);
    $text['jumpoffurl'] = sprintf('%s%suid=%s&jo=1', $url, $sep, $hash);
    #0013076: Blacklisting posibility for unknown users
    $url = getConfig('blacklisturl');
    $sep = strpos($url, '?') === false ? '?' : '&';
    $html['blacklist'] = sprintf('<a href="%s%semail=%s">%s</a>', $url, htmlspecialchars($sep), $email, $strUnsubscribe);
    $text['blacklist'] = sprintf('%s%semail=%s', $url, $sep, $email);
    $html['blacklisturl'] = sprintf('%s%semail=%s', $url, htmlspecialchars($sep), $email);
    $text['blacklisturl'] = sprintf('%s%semail=%s', $url, $sep, $email);
    #0013076: Problem found during testing: message part must be parsed correctly as well.
    if (count($forwardedby) && isset($forwardedby['email'])) {
        $html['unsubscribe'] = $html['blacklist'];
        $text['unsubscribe'] = $text['blacklist'];
        $html['forwardedby'] = $forwardedby['email'];
        $text['forwardedby'] = $forwardedby['email'];
    }
    $url = getConfig('subscribeurl');
    $sep = strpos($url, '?') === false ? '?' : '&';
    $html['subscribe'] = sprintf('<a href="%s">%s</a>', $url, $strThisLink);
    $text['subscribe'] = sprintf('%s', $url);
    $html['subscribeurl'] = sprintf('%s', $url);
    $text['subscribeurl'] = sprintf('%s', $url);
    $url = getConfig('forwardurl');
    $sep = strpos($url, '?') === false ? '?' : '&';
    $html['forward'] = sprintf('<a href="%s%suid=%s&amp;mid=%d">%s</a>', $url, htmlspecialchars($sep), $hash, $messageid, $strThisLink);
    $text['forward'] = sprintf('%s%suid=%s&mid=%d', $url, $sep, $hash, $messageid);
    $html['forwardurl'] = sprintf('%s%suid=%s&amp;mid=%d', $url, htmlspecialchars($sep), $hash, $messageid);
    $text['forwardurl'] = $text['forward'];
    $html['messageid'] = sprintf('%d', $messageid);
    $text['messageid'] = sprintf('%d', $messageid);
    $url = getConfig('forwardurl');
    # make sure there are no newlines, otherwise they get turned into <br/>s
    $html['forwardform'] = '';
    #sprintf('<form method="get" action="%s" name="forwardform" class="forwardform"><input type="hidden" name="uid" value="%s" /><input type="hidden" name="mid" value="%d" /><input type="hidden" name="p" value="forward" /><input type=text name="email" value="" class="forwardinput" /><input name="Send" type="submit" value="%s" class="forwardsubmit"/></form>',$url,$hash,$messageid,$GLOBALS['strForward']);
    $text['signature'] = "\n\n-- powered by phpList, www.phplist.com --\n\n";
    $url = getConfig('preferencesurl');
    $sep = strpos($url, '?') === false ? '?' : '&';
    $html['preferences'] = sprintf('<a href="%s%suid=%s">%s</a>', $url, htmlspecialchars($sep), $hash, $strThisLink);
    $text['preferences'] = sprintf('%s%suid=%s', $url, $sep, $hash);
    $html['preferencesurl'] = sprintf('%s%suid=%s', $url, htmlspecialchars($sep), $hash);
    $text['preferencesurl'] = sprintf('%s%suid=%s', $url, $sep, $hash);
    $url = getConfig('confirmationurl');
    $sep = strpos($url, '?') === false ? '?' : '&';
    $html['confirmationurl'] = sprintf('%s%suid=%s', $url, htmlspecialchars($sep), $hash);
    $text['confirmationurl'] = sprintf('%s%suid=%s', $url, $sep, $hash);
    #historical, not sure it's still used
    $html['userid'] = $hash;
    $text['userid'] = $hash;
    $html['website'] = $GLOBALS['website'];
    # Your website's address, e.g. www.yourdomain.com
    $text['website'] = $GLOBALS['website'];
    $html['domain'] = $GLOBALS['domain'];
    # Your domain, e.g. yourdomain.com
    $text['domain'] = $GLOBALS['domain'];
    if ($hash != 'forwarded') {
        $text['footer'] = $cached[$messageid]['textfooter'];
        $html['footer'] = $cached[$messageid]['htmlfooter'];
    } else {
        #0013076: different content when forwarding 'to a friend'
        if (FORWARD_ALTERNATIVE_CONTENT) {
            $text['footer'] = stripslashes($messagedata['forwardfooter']);
        } else {
            $text['footer'] = getConfig('forwardfooter');
        }
        $html['footer'] = $text['footer'];
    }
    /*
      We request you retain the signature below in your emails including the links.
      This not only gives respect to the large amount of time given freely
      by the developers  but also helps build interest, traffic and use of
      phpList, which is beneficial to it's future development.
    
      You can configure how the credits are added to your pages and emails in your
      config file.
    
      Michiel Dethmers, phpList Ltd 2003 - 2013
    */
    if (!EMAILTEXTCREDITS) {
        $html['signature'] = $PoweredByImage;
        #'<div align="center" id="signature"><a href="http://www.phplist.com"><img src="powerphplist.png" width=88 height=31 title="Powered by PHPlist" alt="Powered by PHPlist" border="0" /></a></div>';
        # oops, accidentally became spyware, never intended that, so take it out again :-)
        $html['signature'] = preg_replace('/src=".*power-phplist.png"/', 'src="powerphplist.png"', $html['signature']);
    } else {
        $html['signature'] = $PoweredByText;
    }
    #  $content = $cached[$messageid]["htmlcontent"];
    if (VERBOSE && $getspeedstats) {
        output('define placeholders end');
    }
    ## Fill text and html versions depending on given versions.
    if (VERBOSE && $getspeedstats) {
        output('parse text to html or html to text start');
    }
    if ($cached[$messageid]['htmlformatted']) {
        if (empty($cached[$messageid]['textcontent'])) {
            $textcontent = HTML2Text($content);
        } else {
            $textcontent = $cached[$messageid]['textcontent'];
        }
        $htmlcontent = $content;
    } else {
        if (empty($cached[$messageid]['textcontent'])) {
            $textcontent = $content;
        } else {
            $textcontent = $cached[$messageid]['textcontent'];
        }
        $htmlcontent = parseText($content);
    }
    if (VERBOSE && $getspeedstats) {
        output('parse text to html or html to text end');
    }
    $defaultstyle = getConfig('html_email_style');
    $adddefaultstyle = 0;
    if (VERBOSE && $getspeedstats) {
        output('merge into template start');
    }
    if ($cached[$messageid]['template']) {
        # template used
        $htmlmessage = str_replace('[CONTENT]', $htmlcontent, $cached[$messageid]['template']);
    } else {
        # no template used
        $htmlmessage = $htmlcontent;
        $adddefaultstyle = 1;
    }
    $textmessage = $textcontent;
    if (VERBOSE && $getspeedstats) {
        output('merge into template end');
    }
    ## Parse placeholders
    if (VERBOSE && $getspeedstats) {
        output('parse placeholders start');
    }
    /*
      var_dump($html);
      var_dump($userdata);
      var_dump($user_att_values);
      exit;
    */
    #  print htmlspecialchars($htmlmessage);exit;
    ### @@@TODO don't use forward and forward form in a forwarded message as it'll fail
    if (strpos($htmlmessage, '[FOOTER]') !== false) {
        $htmlmessage = str_ireplace('[FOOTER]', $html['footer'], $htmlmessage);
    } elseif ($html['footer']) {
        $htmlmessage = addHTMLFooter($htmlmessage, '<br />' . $html['footer']);
    }
    if (strpos($htmlmessage, '[SIGNATURE]') !== false) {
        $htmlmessage = str_ireplace('[SIGNATURE]', $html['signature'], $htmlmessage);
    } else {
        # BUGFIX 0015303, 2/2
        //    $htmlmessage .= '<br />'.$html["signature"];
        $htmlmessage = addHTMLFooter($htmlmessage, '
' . $html['signature']);
    }
    # END BUGFIX 0015303, 2/2
    if (strpos($textmessage, '[FOOTER]')) {
        $textmessage = str_ireplace('[FOOTER]', $text['footer'], $textmessage);
    } else {
        $textmessage .= "\n\n" . $text['footer'];
    }
    if (strpos($textmessage, '[SIGNATURE]')) {
        $textmessage = str_ireplace('[SIGNATURE]', $text['signature'], $textmessage);
    } else {
        $textmessage .= "\n" . $text['signature'];
    }
    ### addition to handle [FORWARDURL:Message ID:Link Text] (link text optional)
    while (preg_match('/\\[FORWARD:([^\\]]+)\\]/Uxm', $htmlmessage, $regs)) {
        $newforward = $regs[1];
        $matchtext = $regs[0];
        if (strpos($newforward, ':')) {
            ## using FORWARDURL:messageid:linktext
            list($forwardmessage, $forwardtext) = explode(':', $newforward);
        } else {
            $forwardmessage = sprintf('%d', $newforward);
            $forwardtext = 'this link';
        }
        if (!empty($forwardmessage)) {
            $url = getConfig('forwardurl');
            $sep = strpos($url, '?') === false ? '?' : '&';
            $forwardurl = sprintf('%s%suid=%s&mid=%d', $url, $sep, $hash, $forwardmessage);
            $htmlmessage = str_replace($matchtext, '<a href="' . htmlspecialchars($forwardurl) . '">' . $forwardtext . '</a>', $htmlmessage);
        } else {
            ## make sure to remove the match, otherwise, it'll be an eternal loop
            $htmlmessage = str_replace($matchtext, '', $htmlmessage);
        }
    }
    ## the text message has to be parsed seperately, because the line might wrap if the text for the link is long, so the match text is different
    while (preg_match('/\\[FORWARD:([^\\]]+)\\]/Uxm', $textmessage, $regs)) {
        $newforward = $regs[1];
        $matchtext = $regs[0];
        if (strpos($newforward, ':')) {
            ## using FORWARDURL:messageid:linktext
            list($forwardmessage, $forwardtext) = explode(':', $newforward);
        } else {
            $forwardmessage = sprintf('%d', $newforward);
            $forwardtext = 'this link';
        }
        if (!empty($forwardmessage)) {
            $url = getConfig('forwardurl');
            $sep = strpos($url, '?') === false ? '?' : '&';
            $forwardurl = sprintf('%s%suid=%s&mid=%d', $url, $sep, $hash, $forwardmessage);
            $textmessage = str_replace($matchtext, $forwardtext . ' ' . $forwardurl, $textmessage);
        } else {
            ## make sure to remove the match, otherwise, it'll be an eternal loop
            $textmessage = str_replace($matchtext, '', $textmessage);
        }
    }
    #  $req = Sql_Query(sprintf('select filename,data from %s where template = %d',
    #    $GLOBALS["tables"]["templateimage"],$cached[$messageid]["templateid"]));
    if (ALWAYS_ADD_USERTRACK) {
        if (stripos($htmlmessage, '</body>')) {
            $htmlmessage = str_replace('</body>', '<img src="' . $GLOBALS['public_scheme'] . '://' . $website . $GLOBALS['pageroot'] . '/ut.php?u=' . $hash . '&amp;m=' . $messageid . '" width="1" height="1" border="0" alt="" /></body>', $htmlmessage);
        } else {
            $htmlmessage .= '<img src="' . $GLOBALS['public_scheme'] . '://' . $website . $GLOBALS['pageroot'] . '/ut.php?u=' . $hash . '&amp;m=' . $messageid . '" width="1" height="1" border="0" alt="" />';
        }
    } else {
        ## can't use str_replace or str_ireplace, because those replace all, and we only want to replace one
        $htmlmessage = preg_replace('/\\[USERTRACK\\]/i', '<img src="' . $GLOBALS['public_scheme'] . '://' . $website . $GLOBALS['pageroot'] . '/ut.php?u=' . $hash . '&amp;m=' . $messageid . '" width="1" height="1" border="0" alt="" />', $htmlmessage, 1);
    }
    # make sure to only include usertrack once, otherwise the stats would go silly
    $htmlmessage = str_ireplace('[USERTRACK]', '', $htmlmessage);
    $textmessage = str_ireplace('[USERTRACK]', '', $textmessage);
    $html['subject'] = $cached[$messageid]['subject'];
    $text['subject'] = $cached[$messageid]['subject'];
    $htmlmessage = parsePlaceHolders($htmlmessage, $html);
    $textmessage = parsePlaceHolders($textmessage, $text);
    if (VERBOSE && $getspeedstats) {
        output('parse placeholders end');
    }
    if (VERBOSE && $getspeedstats) {
        output('parse userdata start');
    }
    $htmlmessage = parsePlaceHolders($htmlmessage, $userdata);
    $textmessage = parsePlaceHolders($textmessage, $userdata);
    //CUT 2
    $destinationemail = '';
    if (is_array($user_att_values)) {
        // CUT 3
        $htmlmessage = parsePlaceHolders($htmlmessage, $user_att_values);
        $textmessage = parsePlaceHolders($textmessage, $user_att_values);
    }
    if (VERBOSE && $getspeedstats) {
        output('parse userdata end');
    }
    if (!$destinationemail) {
        $destinationemail = $email;
    }
    # this should move into a plugin
    if (strpos($destinationemail, '@') === false && isset($GLOBALS['expand_unqualifiedemail'])) {
        $destinationemail .= $GLOBALS['expand_unqualifiedemail'];
    }
    if (VERBOSE && $getspeedstats) {
        output('pass to plugins for destination email start');
    }
    foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
        #    print "Checking Destination for ".$plugin->name."<br/>";
        $destinationemail = $plugin->setFinalDestinationEmail($messageid, $user_att_values, $destinationemail);
    }
    if (VERBOSE && $getspeedstats) {
        output('pass to plugins for destination email end');
    }
    foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
        $textmessage = $plugin->parseOutgoingTextMessage($messageid, $textmessage, $destinationemail, $userdata);
        $htmlmessage = $plugin->parseOutgoingHTMLMessage($messageid, $htmlmessage, $destinationemail, $userdata);
    }
    ## click tracking
    # for now we won't click track forwards, as they are not necessarily users, so everything would fail
    if (VERBOSE && $getspeedstats) {
        output('click track start');
    }
    if (CLICKTRACK && $hash != 'forwarded' && !empty($userdata['id'])) {
        $urlbase = '';
        # let's leave this for now
        /*
        if (preg_match('/<base href="(.*)"([^>]*)>/Umis',$htmlmessage,$regs)) {
          $urlbase = $regs[1];
        } else {
          $urlbase = '';
        }
        #    print "URLBASE: $urlbase<br/>";
        */
        # convert html message
        #    preg_match_all('/<a href="?([^> "]*)"?([^>]*)>(.*)<\/a>/Umis',$htmlmessage,$links);
        preg_match_all('/<a (.*)href=["\'](.*)["\']([^>]*)>(.*)<\\/a>/Umis', $htmlmessage, $links);
        # to process the Yahoo webpage with base href and link like <a href=link> we'd need this one
        #    preg_match_all('/<a href=([^> ]*)([^>]*)>(.*)<\/a>/Umis',$htmlmessage,$links);
        $clicktrack_root = sprintf('%s://%s/lt.php', $GLOBALS['public_scheme'], $website . $GLOBALS['pageroot']);
        for ($i = 0; $i < count($links[2]); ++$i) {
            $link = cleanUrl($links[2][$i]);
            $link = str_replace('"', '', $link);
            if (preg_match('/\\.$/', $link)) {
                $link = substr($link, 0, -1);
            }
            $linkid = 0;
            $linktext = $links[4][$i];
            ## if the link is text containing a "protocol" eg http:// then do not track it, otherwise
            ## it will look like Phishing
            ## it's ok when the link is an image
            $linktext = strip_tags($linktext);
            $looksLikePhishing = stripos($linktext, 'https://') !== false || stripos($linktext, 'http://') !== false;
            if (!$looksLikePhishing && (preg_match('/^http|ftp/i', $link) || preg_match('/^http|ftp/i', $urlbase)) && !strpos($link, $clicktrack_root)) {
                # take off personal uids
                $url = cleanUrl($link, array('PHPSESSID', 'uid'));
                #        $url = preg_replace('/&uid=[^\s&]+/','',$link);
                #        if (!strpos('http:',$link)) {
                #          $link = $urlbase . $link;
                #        }
                $linkid = clickTrackLinkId($messageid, $userdata['id'], $url, $link);
                $masked = "H|{$linkid}|{$messageid}|" . $userdata['id'] ^ XORmask;
                $masked = base64_encode($masked);
                ## 15254- the encoding adds one or two extraneous = signs, take them off
                $masked = preg_replace('/=$/', '', $masked);
                $masked = preg_replace('/=$/', '', $masked);
                $masked = urlencode($masked);
                if (!CLICKTRACK_LINKMAP) {
                    $newlink = sprintf('<a %shref="%s://%s/lt.php?id=%s" %s>%s</a>', $links[1][$i], $GLOBALS['public_scheme'], $website . $GLOBALS['pageroot'], $masked, $links[3][$i], $links[4][$i]);
                } else {
                    $newlink = sprintf('<a %shref="%s://%s%s" %s>%s</a>', $links[1][$i], $GLOBALS['public_scheme'], $website . CLICKTRACK_LINKMAP, $masked, $links[3][$i], $links[4][$i]);
                }
                $htmlmessage = str_replace($links[0][$i], $newlink, $htmlmessage);
            }
        }
        # convert Text message
        # first find occurances of our top domain, to avoid replacing them later
        # hmm, this is no point, it's not just *our* topdomain, but any
        if (0) {
            preg_match_all('#(https?://' . $GLOBALS['website'] . '/?)\\s+#mis', $textmessage, $links);
            #    preg_match_all('#(https?://[a-z0-9\./\#\?&:@=%\-]+)#ims',$textmessage,$links);
            #    preg_match_all('!(https?:\/\/www\.[a-zA-Z0-9\.\/#~\?+=&%@-_]+)!mis',$textmessage,$links);
            for ($i = 0; $i < count($links[1]); ++$i) {
                # not entirely sure why strtolower was used, but it seems to break things http://mantis.phplist.com/view.php?id=4406
                #      $link = strtolower(cleanUrl($links[1][$i]));
                $link = cleanUrl($links[1][$i]);
                if (preg_match('/\\.$/', $link)) {
                    $link = substr($link, 0, -1);
                }
                $linkid = 0;
                if (preg_match('/^http|ftp/i', $link) && !strpos($link, $clicktrack_root)) {
                    $url = cleanUrl($link, array('PHPSESSID', 'uid'));
                    $req = Sql_Query(sprintf('insert ignore into %s (messageid,userid,url,forward)
          values(%d,%d,"%s","%s")', $GLOBALS['tables']['linktrack'], $messageid, $userdata['id'], $url, $link));
                    $req = Sql_Fetch_Row_Query(sprintf('select linkid from %s where messageid = %s and userid = %d and forward = "%s"
        ', $GLOBALS['tables']['linktrack'], $messageid, $userdata['id'], $link));
                    $linkid = $req[0];
                    $masked = "T|{$linkid}|{$messageid}|" . $userdata['id'] ^ XORmask;
                    $masked = urlencode(base64_encode($masked));
                    $newlink = sprintf('%s://%s/lt.php?id=%s', $GLOBALS['public_scheme'], $website . $GLOBALS['pageroot'], $masked);
                    $textmessage = str_replace($links[0][$i], '<' . $newlink . '>', $textmessage);
                }
            }
        }
        #now find the rest
        # @@@ needs to expand to find complete urls like:
        #http://user:password@www.web-site.com:1234/document.php?parameter=something&otherpar=somethingelse#anchor
        # or secure
        #https://user:password@www.website.com:2345/document.php?parameter=something%20&otherpar=somethingelse#anchor
        preg_match_all('#(https?://[^\\s\\>\\}\\,]+)#mis', $textmessage, $links);
        #    preg_match_all('#(https?://[a-z0-9\./\#\?&:@=%\-]+)#ims',$textmessage,$links);
        #    preg_match_all('!(https?:\/\/www\.[a-zA-Z0-9\.\/#~\?+=&%@-_]+)!mis',$textmessage,$links);
        ## sort the results in reverse order, so that they are replaced correctly
        rsort($links[1]);
        $newlinks = array();
        for ($i = 0; $i < count($links[1]); ++$i) {
            $link = cleanUrl($links[1][$i]);
            if (preg_match('/\\.$/', $link)) {
                $link = substr($link, 0, -1);
            }
            $linkid = 0;
            if (preg_match('/^http|ftp/i', $link)) {
                # && !strpos($link,$clicktrack_root)) {
                $url = cleanUrl($link, array('PHPSESSID', 'uid'));
                $linkid = clickTrackLinkId($messageid, $userdata['id'], $url, $link);
                $masked = "T|{$linkid}|{$messageid}|" . $userdata['id'] ^ XORmask;
                $masked = base64_encode($masked);
                ## 15254- the encoding adds one or two extraneous = signs, take them off
                $masked = preg_replace('/=$/', '', $masked);
                $masked = preg_replace('/=$/', '', $masked);
                $masked = urlencode($masked);
                if (!CLICKTRACK_LINKMAP) {
                    $newlinks[$linkid] = sprintf('%s://%s/lt.php?id=%s', $GLOBALS['public_scheme'], $website . $GLOBALS['pageroot'], $masked);
                } else {
                    $newlinks[$linkid] = sprintf('%s://%s%s', $GLOBALS['public_scheme'], $website . CLICKTRACK_LINKMAP, $masked);
                }
                #        print $links[0][$i] .' -> '.$newlink.'<br/>';
                $textmessage = str_replace($links[1][$i], '[%%%' . $linkid . '%%%]', $textmessage);
            }
        }
        foreach ($newlinks as $linkid => $newlink) {
            $textmessage = str_replace('[%%%' . $linkid . '%%%]', $newlink, $textmessage);
        }
    }
    if (VERBOSE && $getspeedstats) {
        output('click track end');
    }
    ## if we're not tracking clicks, we should add Google tracking here
    ## otherwise, we can add it when redirecting on the click
    if (!CLICKTRACK && !empty($cached[$messageid]['google_track'])) {
        preg_match_all('/<a (.*)href=["\'](.*)["\']([^>]*)>(.*)<\\/a>/Umis', $htmlmessage, $links);
        for ($i = 0; $i < count($links[2]); ++$i) {
            $link = cleanUrl($links[2][$i]);
            $link = str_replace('"', '', $link);
            ## http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=55578
            $trackingcode = 'utm_source=phplist' . $messageid . '&utm_medium=email&utm_content=HTML&utm_campaign=' . urlencode($cached[$messageid]['subject']);
            ## take off existing tracking code, if found
            if (strpos($link, 'utm_medium') !== false) {
                $link = preg_replace('/utm_(\\w+)\\=[^&]+&/U', '', $link);
            }
            ## 16894 make sure to keep the fragment value at the end of the URL
            if (strpos($link, '#')) {
                list($tmplink, $fragment) = explode('#', $link);
                $link = $tmplink;
                unset($tmplink);
                $fragment = '#' . $fragment;
            } else {
                $fragment = '';
            }
            if (strpos($link, '?')) {
                $newurl = $link . '&' . $trackingcode . $fragment;
            } else {
                $newurl = $link . '?' . $trackingcode . $fragment;
            }
            #   print $link. ' '.$newurl.' <br/>';
            $newlink = sprintf('<a %shref="%s" %s>%s</a>', $links[1][$i], $newurl, $links[3][$i], $links[4][$i]);
            $htmlmessage = str_replace($links[0][$i], $newlink, $htmlmessage);
        }
        preg_match_all('#(https?://[^\\s\\>\\}\\,]+)#mis', $textmessage, $links);
        rsort($links[1]);
        $newlinks = array();
        for ($i = 0; $i < count($links[1]); ++$i) {
            $link = cleanUrl($links[1][$i]);
            if (preg_match('/\\.$/', $link)) {
                $link = substr($link, 0, -1);
            }
            if (preg_match('/^http|ftp/i', $link)) {
                # && !strpos($link,$clicktrack_root)) {
                $url = cleanUrl($link, array('PHPSESSID', 'uid'));
                //@alpha1: maybe source should be message id?
                $trackingcode = 'utm_source=phplist' . $messageid . '&utm_medium=email&utm_content=text&utm_campaign=' . urlencode($cached[$messageid]['subject']);
                ## take off existing tracking code, if found
                if (strpos($link, 'utm_medium') !== false) {
                    $link = preg_replace('/utm_(\\w+)\\=[^&]+/', '', $link);
                }
                ## 16894 make sure to keep the fragment value at the end of the URL
                if (strpos($link, '#')) {
                    list($tmplink, $fragment) = explode('#', $link);
                    $link = $tmplink;
                    unset($tmplink);
                    $fragment = '#' . $fragment;
                } else {
                    $fragment = '';
                }
                if (strpos($link, '?')) {
                    $newurl = $link . '&' . $trackingcode . $fragment;
                } else {
                    $newurl = $link . '?' . $trackingcode . $fragment;
                }
                $newlinks[$i] = $newurl;
                $textmessage = str_replace($links[1][$i], '[%%%' . $i . '%%%]', $textmessage);
            }
        }
        foreach ($newlinks as $linkid => $newlink) {
            $textmessage = str_replace('[%%%' . $linkid . '%%%]', $newlink, $textmessage);
        }
        unset($newlinks);
    }
    #  print htmlspecialchars($htmlmessage);exit;
    #0011996: forward to friend - personal message
    if (FORWARD_PERSONAL_NOTE_SIZE && $hash == 'forwarded' && !empty($forwardedby['personalNote'])) {
        $htmlmessage = nl2br($forwardedby['personalNote']) . '<br/>' . $htmlmessage;
        $textmessage = $forwardedby['personalNote'] . "\n" . $textmessage;
    }
    if (VERBOSE && $getspeedstats) {
        output('cleanup start');
    }
    ## allow fallback to default value for the ones that do not have a value
    ## delimiter is %% to avoid interfering with markup
    preg_match_all('/\\[.*\\%\\%([^\\]]+)\\]/Ui', $htmlmessage, $matches);
    for ($i = 0; $i < count($matches[0]); ++$i) {
        $htmlmessage = str_ireplace($matches[0][$i], $matches[1][$i], $htmlmessage);
    }
    preg_match_all('/\\[.*\\%\\%([^\\]]+)\\]/Ui', $textmessage, $matches);
    for ($i = 0; $i < count($matches[0]); ++$i) {
        $textmessage = str_ireplace($matches[0][$i], $matches[1][$i], $textmessage);
    }
    ## remove any remaining placeholders
    ## 16671 - do not do this, as it'll remove conditional CSS and other stuff
    ## that we'd like to keep
    //$htmlmessage = preg_replace("/\[[A-Z\. ]+\]/i","",$htmlmessage);
    //$textmessage = preg_replace("/\[[A-Z\. ]+\]/i","",$textmessage);
    #  print htmlspecialchars($htmlmessage);exit;
    # check that the HTML message as proper <head> </head> and <body> </body> tags
    # some readers fail when it doesn't
    if (!preg_match('#<body.*</body>#ims', $htmlmessage)) {
        $htmlmessage = '<body>' . $htmlmessage . '</body>';
    }
    if (!preg_match('#<head.*</head>#ims', $htmlmessage)) {
        if (!$adddefaultstyle) {
            $defaultstyle = '';
        }
        $htmlmessage = '<head>
        <meta content="text/html;charset=' . $cached[$messageid]['html_charset'] . '" http-equiv="Content-Type">
        <title></title>' . $defaultstyle . '</head>' . $htmlmessage;
    }
    if (!preg_match('#<html.*</html>#ims', $htmlmessage)) {
        $htmlmessage = '<html>' . $htmlmessage . '</html>';
    }
    ## remove trailing code after </html>
    $htmlmessage = preg_replace('#</html>.*#msi', '</html>', $htmlmessage);
    ## the editor sometimes places <p> and </p> around the URL
    $htmlmessage = str_ireplace('<p><!DOCTYPE', '<!DOCTYPE', $htmlmessage);
    $htmlmessage = str_ireplace('</html></p>', '</html>', $htmlmessage);
    if (VERBOSE && $getspeedstats) {
        output('cleanup end');
    }
    #  $htmlmessage = compressContent($htmlmessage);
    # print htmlspecialchars($htmlmessage);exit;
    if ($getspeedstats) {
        output('build Start ' . $GLOBALS['processqueue_timer']->interval(1));
    }
    # build the email
    $mail = new PHPlistMailer($messageid, $destinationemail);
    if ($isTestMail) {
        $mail->SMTPDebug = PHPMAILER_SMTP_DEBUG;
        $mail->Debugoutput = 'html';
    }
    if ($forwardedby) {
        $mail->add_timestamp();
    }
    $mail->addCustomHeader('List-Help: <' . $text['preferences'] . '>');
    $mail->addCustomHeader('List-Unsubscribe: <' . $text['jumpoffurl'] . '>');
    $mail->addCustomHeader('List-Subscribe: <' . getConfig('subscribeurl') . '>');
    $mail->addCustomHeader('List-Owner: <mailto:' . getConfig('admin_address') . '>');
    list($dummy, $domaincheck) = explode('@', $destinationemail);
    $text_domains = explode("\n", trim(getConfig('alwayssendtextto')));
    if (in_array($domaincheck, $text_domains)) {
        $htmlpref = 0;
        if (VERBOSE) {
            output($GLOBALS['I18N']->get('sendingtextonlyto') . " {$domaincheck}");
        }
    }
    foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
        $plugin_attachments = $plugin->getMessageAttachment($messageid, $mail->Body);
        if (!empty($plugin_attachments[0]['content'])) {
            foreach ($plugins_attachments as $plugin_attachment) {
                $mail->add_attachment($plugin_attachment['content'], basename($plugin_attachment['filename']), $plugin_attachment['mimetype']);
            }
        }
    }
    # so what do we actually send?
    switch ($cached[$messageid]['sendformat']) {
        case 'PDF':
            # send a PDF file to users who want html and text to everyone else
            if ($htmlpref) {
                if (!$isTestMail) {
                    Sql_Query("update {$GLOBALS['tables']['message']} set aspdf = aspdf + 1 where id = {$messageid}");
                }
                $pdffile = createPdf($textmessage);
                if (is_file($pdffile) && filesize($pdffile)) {
                    $fp = fopen($pdffile, 'r');
                    if ($fp) {
                        $contents = fread($fp, filesize($pdffile));
                        fclose($fp);
                        unlink($pdffile);
                        $html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
              <html>
              <head>
                <title></title>
              </head>
              <body>
              <embed src="message.pdf" width="450" height="450" href="message.pdf"></embed>
              </body>
              </html>';
                        #            $mail->add_html($html,$textmessage);
                        #            $mail->add_text($textmessage);
                        $mail->add_attachment($contents, 'message.pdf', 'application/pdf');
                    }
                }
                if (!addAttachments($messageid, $mail, 'HTML')) {
                    return 0;
                }
            } else {
                if (!$isTestMail) {
                    Sql_Query("update {$GLOBALS['tables']['message']} set astext = astext + 1 where id = {$messageid}");
                }
                $mail->add_text($textmessage);
                if (!addAttachments($messageid, $mail, 'text')) {
                    return 0;
                }
            }
            break;
        case 'text and PDF':
            # send a PDF file to users who want html and text to everyone else
            if ($htmlpref) {
                if (!$isTestMail) {
                    Sql_Query("update {$GLOBALS['tables']['message']} set astextandpdf = astextandpdf + 1 where id = {$messageid}");
                }
                $pdffile = createPdf($textmessage);
                if (is_file($pdffile) && filesize($pdffile)) {
                    $fp = fopen($pdffile, 'r');
                    if ($fp) {
                        $contents = fread($fp, filesize($pdffile));
                        fclose($fp);
                        unlink($pdffile);
                        $html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
              <html>
              <head>
                <title></title>
              </head>
              <body>
              <embed src="message.pdf" width="450" height="450" href="message.pdf"></embed>
              </body>
              </html>';
                        #           $mail->add_html($html,$textmessage);
                        $mail->add_text($textmessage);
                        $mail->add_attachment($contents, 'message.pdf', 'application/pdf');
                    }
                }
                if (!addAttachments($messageid, $mail, 'HTML')) {
                    return 0;
                }
            } else {
                if (!$isTestMail) {
                    Sql_Query("update {$GLOBALS['tables']['message']} set astext = astext + 1 where id = {$messageid}");
                }
                $mail->add_text($textmessage);
                if (!addAttachments($messageid, $mail, 'text')) {
                    return 0;
                }
            }
            break;
        case 'text':
            # send as text
            if (!$isTestMail) {
                Sql_Query("update {$GLOBALS['tables']['message']} set astext = astext + 1 where id = {$messageid}");
            }
            $mail->add_text($textmessage);
            if (!addAttachments($messageid, $mail, 'text')) {
                return 0;
            }
            break;
        case 'both':
        case 'text and HTML':
        case 'HTML':
        default:
            $handled_by_plugin = 0;
            if (!empty($GLOBALS['pluginsendformats'][$cached[$messageid]['sendformat']])) {
                # possibly handled by plugin
                $pl = $GLOBALS['plugins'][$GLOBALS['pluginsendformats'][$cached[$messageid]['sendformat']]];
                if (is_object($pl) && method_exists($pl, 'parseFinalMessage')) {
                    $handled_by_plugin = $pl->parseFinalMessage($cached[$messageid]['sendformat'], $htmlmessage, $textmessage, $mail, $messageid);
                }
            }
            if (!$handled_by_plugin) {
                # send one big file to users who want html and text to everyone else
                if ($htmlpref) {
                    if (!$isTestMail) {
                        Sql_Query("update {$GLOBALS['tables']['message']} set astextandhtml = astextandhtml + 1 where id = {$messageid}");
                    }
                    #  dbg("Adding HTML ".$cached[$messageid]["templateid"]);
                    if (WORDWRAP_HTML) {
                        ## wrap it: http://mantis.phplist.com/view.php?id=15528
                        ## some reports say, this fixes things and others say it breaks things https://mantis.phplist.com/view.php?id=15617
                        ## so for now, only switch on if requested.
                        ## it probably has to do with the MTA used
                        $htmlmessage = wordwrap($htmlmessage, WORDWRAP_HTML, "\r\n");
                    }
                    $mail->add_html($htmlmessage, $textmessage, $cached[$messageid]['templateid']);
                    if (!addAttachments($messageid, $mail, 'HTML')) {
                        return 0;
                    }
                } else {
                    if (!$isTestMail) {
                        Sql_Query("update {$GLOBALS['tables']['message']} set astext = astext + 1 where id = {$messageid}");
                    }
                    $mail->add_text($textmessage);
                    #          $mail->setText($textmessage);
                    #          $mail->Encoding = TEXTEMAIL_ENCODING;
                    if (!addAttachments($messageid, $mail, 'text')) {
                        return 0;
                    }
                }
            }
            break;
    }
    #  print htmlspecialchars($htmlmessage);exit;
    if (!TEST) {
        if ($hash != 'forwarded' || !count($forwardedby)) {
            $fromname = $cached[$messageid]['fromname'];
            $fromemail = $cached[$messageid]['fromemail'];
            $subject = $cached[$messageid]['subject'];
        } else {
            $fromname = '';
            $fromemail = $forwardedby['email'];
            $subject = $GLOBALS['strFwd'] . ': ' . $cached[$messageid]['subject'];
        }
        if (!empty($cached[$messageid]['replytoemail'])) {
            $mail->AddReplyTo($cached[$messageid]['replytoemail'], $cached[$messageid]['replytoname']);
        }
        if ($getspeedstats) {
            output('build End ' . $GLOBALS['processqueue_timer']->interval(1));
        }
        if ($getspeedstats) {
            output('send Start ' . $GLOBALS['processqueue_timer']->interval(1));
        }
        if (!empty($GLOBALS['developer_email'])) {
            $destinationemail = $GLOBALS['developer_email'];
        }
        $sendOK = false;
        if (!$mail->compatSend('', $destinationemail, $fromname, $fromemail, $subject)) {
            foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
                $plugin->processSendFailed($messageid, $userdata, $isTestMail);
            }
            output(sprintf(s('Error sending message %d (%d/%d) to %s (%s) '), $messageid, $counters['batch_count'], $counters['batch_total'], $email, $destinationemail), 0);
        } else {
            $sendOK = true;
            foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
                $plugin->processSendSuccess($messageid, $userdata, $isTestMail);
            }
        }
        if ($getspeedstats) {
            output('send End ' . $GLOBALS['processqueue_timer']->interval(1));
        }
        if (!empty($mail->mailsize)) {
            $sizename = $htmlpref ? 'htmlsize' : 'textsize';
            if (empty($cached[$messageid][$sizename])) {
                setMessageData($messageid, $sizename, $mail->mailsize);
                $cached[$messageid][$sizename] = $mail->mailsize;
                if (isset($cached[$messageid]['htmlsize'])) {
                    output(sprintf(s('Size of HTML email: %s ', formatBytes($cached[$messageid]['htmlsize']))), 0, 'progress');
                }
                if (isset($cached[$messageid]['textsize'])) {
                    output(sprintf(s('Size of Text email: %s ', formatBytes($cached[$messageid]['textsize']))), 0, 'progress');
                }
            }
        }
        if (defined('MAX_MAILSIZE') && isset($cached[$messageid]['htmlsize']) && $cached[$messageid]['htmlsize'] > MAX_MAILSIZE) {
            logEvent(s('Message too large (%s is over %s), suspending', $cached[$messageid]['htmlsize'], MAX_MAILSIZE));
            if ($isTestMail) {
                $_SESSION['action_result'] = s('Warning: the final message exceeds the sending limit, this campaign will fail sending. Reduce the size by removing attachments or images');
            } else {
                Sql_Query(sprintf('update %s set status = "suspended" where id = %d', $GLOBALS['tables']['message'], $messageid));
                logEvent(s('Campaign %d suspended. Message too large', $messageid));
                foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
                    $plugin->processError(s('Campaign %d suspended, message too large', $messageid));
                }
            }
        }
        $sqlCount = $GLOBALS['pagestats']['number_of_queries'] - $sqlCountStart;
        if ($getspeedstats) {
            output('It took ' . $sqlCount . '  queries to send this message');
        }
        return $sendOK;
    }
    return 0;
}
示例#7
0
function repeatMessage($msgid)
{
    #  if (!USE_REPETITION && !USE_rss) return;
    $data = loadMessageData($msgid);
    ## do not repeat when it has already been done
    if (!empty($data['repeatedid'])) {
        return;
    }
    # get the future embargo, either "repeat" minutes after the old embargo
    # or "repeat" after this very moment to make sure that we're not sending the
    # message every time running the queue when there's no embargo set.
    $msgdata = Sql_Fetch_Array_Query(sprintf('select *,date_add(embargo,interval repeatinterval minute) as newembargo,
      date_add(now(),interval repeatinterval minute) as newembargo2, date_add(embargo,interval repeatinterval minute) > now() as isfuture
      from %s where id = %d and repeatuntil > now()', $GLOBALS["tables"]["message"], $msgid));
    if (!$msgdata["id"] || !$msgdata["repeatinterval"]) {
        return;
    }
    # copy the new message
    $query = ' insert into ' . $GLOBALS['tables']['message'] . '    (entered)' . ' values' . '    (current_timestamp)';
    Sql_Query($query);
    $newid = Sql_Insert_Id($GLOBALS['tables']['message'], 'id');
    require dirname(__FILE__) . '/structure.php';
    if (!is_array($DBstruct["message"])) {
        logEvent("Error including structure when trying to duplicate message {$msgid}");
        return;
    }
    foreach ($DBstruct["message"] as $column => $rec) {
        if ($column != "id" && $column != "entered" && $column != "sendstart") {
            Sql_Query(sprintf('update %s set %s = "%s" where id = %d', $GLOBALS["tables"]["message"], $column, addslashes($msgdata[$column]), $newid));
        }
    }
    $req = Sql_Query(sprintf('select * from %s where id = %d', $GLOBALS['tables']['messagedata'], $msgid));
    while ($row = Sql_Fetch_Array($req)) {
        setMessageData($newid, $row['name'], $row['data']);
    }
    # check whether the new embargo is not on an exclusion
    if (isset($GLOBALS["repeat_exclude"]) && is_array($GLOBALS["repeat_exclude"])) {
        $repeatinterval = $msgdata["repeatinterval"];
        $loopcnt = 0;
        while (excludedDateForRepetition($msgdata["newembargo"])) {
            $repeat += $msgdata["repeatinterval"];
            $loopcnt++;
            $msgdata = Sql_Fetch_Array_Query(sprintf('select *,date_add(embargo,interval %d minute) as newembargo,
            date_add(current_timestamp,interval %d minute) as newembargo2, date_add(embargo,interval %d minute) > current_timestamp as isfuture
            from %s where id = %d and repeatuntil > current_timestamp', $repeatinterval, $repeatinterval, $repeatinterval, $GLOBALS["tables"]["message"], $msgid));
            if ($loopcnt > 15) {
                logEvent("Unable to find new embargo date too many exclusions? for message {$msgid}");
                return;
            }
        }
    }
    # correct some values
    if (!$msgdata["isfuture"]) {
        $msgdata["newembargo"] = $msgdata["newembargo2"];
    }
    Sql_Query(sprintf('update %s set embargo = "%s",status = "submitted",sent = "" where id = %d', $GLOBALS["tables"]["message"], $msgdata["newembargo"], $newid));
    list($e['year'], $e['month'], $e['day'], $e['hour'], $e['minute'], $e['second']) = sscanf($msgdata["newembargo"], '%04d-%02d-%02d %02d:%02d:%02d');
    unset($e['second']);
    setMessageData($newid, 'embargo', $e);
    foreach (array("processed", "astext", "ashtml", "astextandhtml", "aspdf", "astextandpdf", "viewed", "bouncecount") as $item) {
        Sql_Query(sprintf('update %s set %s = 0 where id = %d', $GLOBALS["tables"]["message"], $item, $newid));
    }
    # lists
    $req = Sql_Query(sprintf('select listid from %s where messageid = %d', $GLOBALS["tables"]["listmessage"], $msgid));
    while ($row = Sql_Fetch_Row($req)) {
        Sql_Query(sprintf('insert into %s (messageid,listid,entered) values(%d,%d,current_timestamp)', $GLOBALS["tables"]["listmessage"], $newid, $row[0]));
    }
    # attachments
    $req = Sql_Query(sprintf('select * from %s,%s where %s.messageid = %d and %s.attachmentid = %s.id', $GLOBALS["tables"]["message_attachment"], $GLOBALS["tables"]["attachment"], $GLOBALS["tables"]["message_attachment"], $msgid, $GLOBALS["tables"]["message_attachment"], $GLOBALS["tables"]["attachment"]));
    while ($row = Sql_Fetch_Array($req)) {
        if (is_file($row["remotefile"])) {
            # if the "remote file" is actually local, we want to refresh the attachment, so we set
            # filename to nothing
            $row["filename"] = "";
        }
        Sql_Query(sprintf('insert into %s (filename,remotefile,mimetype,description,size)
      values("%s","%s","%s","%s",%d)', $GLOBALS["tables"]["attachment"], addslashes($row["filename"]), addslashes($row["remotefile"]), addslashes($row["mimetype"]), addslashes($row["description"]), $row["size"]));
        $attid = Sql_Insert_Id($GLOBALS['tables']['attachment'], 'id');
        Sql_Query(sprintf('insert into %s (messageid,attachmentid) values(%d,%d)', $GLOBALS["tables"]["message_attachment"], $newid, $attid));
    }
    logEvent("Message {$msgid} was successfully rescheduled as message {$newid}");
    ## remember we duplicated, in order to avoid doing it again (eg when requeuing)
    setMessageData($msgid, 'repeatedid', $newid);
}
示例#8
0
<?php

verifyCsrfGetToken();
# generate text content
$msgid = sprintf('%d', $_GET['id']);
$messagedata = loadMessageData($msgid);
//sleep(10); // to test the busy image
if (preg_match('/\\[URL:(.+)\\]/', $messagedata['message'], $regs)) {
    $content = fetchUrl($regs[1]);
    #  $textversion = 'Fetched '.$regs[1];
    $textversion = HTML2Text($content);
} else {
    $textversion = HTML2Text($messagedata['message']);
}
setMessageData($msgid, 'textmessage', $textversion);
## convert to feedback in the textarea
## @@FIXME this fails when the text is large, or contains £
$textversion = trim($textversion);
$textversion = preg_replace("/\n/", '\\n', $textversion);
$textversion = preg_replace("/\r/", '', $textversion);
$textversion = htmlentities($textversion, ENT_IGNORE, 'UTF-8', true);
$status = '<script type="text/javascript">

$("#textmessage").html("' . str_replace('"', '&quot;', $textversion) . '");
//$("#textmessage").load("./?page=pageaction&action=messagedata&field=textmessage&id=' . $msgid . '");
$("#generatetextversion").hide();

</script>
';
示例#9
0
}
if ($sent > 0 && $totaltime > 0) {
    $msgperhour = (int) (3600 / $totaltime) * $sent;
    $secpermsg = $totaltime / $sent;
    $timeleft = ($num_users - $sent) * $secpermsg;
    $eta = date('D j M H:i', time() + $timeleft);
} else {
    $msgperhour = 0;
    $secpermsg = 0;
    $timeleft = 0;
    $eta = $GLOBALS['I18N']->get('unknown');
}
## 16850 - convert to string, to avoid an SQL error
$msgperhour = "{$msgperhour} ";
setMessageData($id, 'ETA', $eta);
setMessageData($id, 'msg/hr', $msgperhour);
if ($message['status'] != 'inprocess') {
    $html = $GLOBALS['I18N']->get($message['status']);
    if ($message['secstowait'] > 0) {
        $secstowait = secs2time($message['secstowait']);
        $html .= '<br/>' . sprintf($GLOBALS['I18N']->get('%s left until embargo'), $secstowait);
    }
    foreach ($GLOBALS['plugins'] as $plname => $plugin) {
        $html .= $plugin->messageStatus($id, $message['status']);
    }
    if ($message['status'] != 'submitted' && $message['status'] != 'draft') {
        $html .= '<br/>' . PageLinkButton('messages', $GLOBALS['I18N']->get('requeue'), 'resend=' . $message['id'], '', s('Requeue'));
    }
    if (!empty($messagedata['to process'])) {
        $html .= '<br/>' . $messagedata['to process'] . ' ' . $GLOBALS['I18N']->get('still to process') . '<br/>' . $GLOBALS['I18N']->get('sent') . ': ' . $totalsent;
    }
 function processSendingCampaignFinished($messageid, array $messagedata)
 {
     $fixDates = getConfig('dateplaceholder_fixdatesonarchive');
     if ($fixDates) {
         setMessageData($messageid, 'subject', $this->dateParse($messagedata['subject']));
         setMessageData($messageid, 'message', $this->dateParse($messagedata['message']));
         setMessageData($messageid, 'textmessage', $this->dateParse($messagedata['textmessage']));
         setMessageData($messageid, 'footer', $this->dateParse($messagedata['footer']));
     }
 }
 public function replaceMessageAreas($new)
 {
     setMessageData($this->messageId, $this->name, $new);
 }