Main Page | Directories | File List | File Members

sendmail.php

Go to the documentation of this file.
00001 <?php
00002 # This file is part of the Savane project
00003 # <http://gna.org/projects/savane/>
00004 #
00005 # $Id: sendmail.php 5442 2006-02-19 15:14:12Z yeupou $
00006 #
00007 #  Copyright 2003-2005 (c) Mathieu Roy <yeupou--gnu.org>
00008 # 
00009 # The Savane project is free software; you can redistribute it and/or
00010 # modify it under the terms of the GNU General Public License
00011 # as published by the Free Software Foundation; either version 2
00012 # of the License, or (at your option) any later version.
00013 #
00014 # The Savane project is distributed in the hope that it will be useful,
00015 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 # GNU General Public License for more details.
00018 #
00019 # You should have received a copy of the GNU General Public License
00020 # along with the Savane project; if not, write to the Free Software
00021 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023 # Every mails sent should be using functions listed here.
00024 
00025 # The function that finally send the mail.
00026 # Every mail sent by Savannah should be using that function which
00027 # works like mail().
00028 # Note: $to can be a coma-separated list.
00029 #       $from and $to can contain user names
00030 function sendmail_mail ($from, 
00031                         $to, 
00032                         $subject, 
00033                         $message,  #4
00034                         $savannah_project=0, 
00035                         $savannah_artifact=0, 
00036                         $savannah_artifact_id=0, 
00037                         $reply_to=0, # 8
00038                         $additional_headers=0,
00039                         $exclude_list=0) 
00040 {
00041 
00042 
00043   # Make sure that users cannot insert malicious content
00044   # (apart in message, which is not part of the headers)
00045   $to = stripslashes($to);
00046   $from = stripslashes($from);
00047   $subject = stripslashes($subject);
00048 
00049   # Make sure the message respect the 78chars max width
00050   # Make also sure we havent got excessive slashes escaping
00051   $message = wordwrap($message, 78);
00052 
00053   # Convert ; into
00054   $to = ereg_replace(";", ",", $to);
00055   # Transform $to in an ordered list, without duplicates
00056   # (remove blankspaces)
00057   $to = array_unique(explode(",", ereg_replace(" ", "", $to)));
00058 
00059   # If $from is a login name, write nice From: field
00060   $fromuid = user_getid($from);
00061   if (user_exists($fromuid))
00062     {
00063       $from = user_getrealname($fromuid, 1)." <".user_getemail($fromuid).">";
00064     }
00065 
00066   # Write the add. headers 
00067   # Note: RFC-821 recommends to use \r\n as line break in headers but \n
00068   # works and there are report of failures with \r\n so we let \n for now.
00069   $more_headers = "From: ".sendmail_encode_header_content($from)."\n";
00070   if ($reply_to)
00071     { $more_headers .= "Reply-To: ".$reply_to."\n"; }
00072   $more_headers .= "X-Savane-Server: ".$_SERVER['SERVER_NAME'].":".$_SERVER['SERVER_PORT']." [".$_SERVER['SERVER_ADDR']."]\n";
00073 
00074   # Necessary for proper utf-8 support
00075   $more_headers .= "MIME-Version: 1.0\n";
00076   $more_headers .= "Content-Type: text/plain;charset=UTF-8\n";
00077 
00078   # Savane details
00079   if ($savannah_project) 
00080     { $more_headers .= "X-Savane-Project: ".$savannah_project."\n"; }
00081   if ($savannah_artifact) 
00082     { $more_headers .= "X-Savane-Tracker: ".$savannah_artifact."\n"; }  
00083   if ($savannah_artifact_id) 
00084     { $more_headers .= "X-Savane-Item-ID: ".$savannah_artifact_id."\n"; }
00085   if ($additional_headers) 
00086     { $more_headers .= $additional_headers."\n";  }
00087 
00088   # User details.
00089   # Tell what is the user agent, tell which authenticated user made
00090   # the mail to be sent
00091   $more_headers .= "User-Agent: ".$_SERVER['HTTP_USER_AGENT']."\n";
00092   if (user_isloggedin())
00093     {
00094       $more_headers .= "X-Apparently-From: ".$_SERVER['REMOTE_ADDR']." (Savane authenticated user ".user_getname(user_getid()).")\n";
00095     }
00096   else
00097     {
00098       $more_headers .= "X-Apparently-From: ".$_SERVER['REMOTE_ADDR']."\n";
00099     }
00100 
00101   # Message ID
00102   $msg_id = sendmail_create_msgid();
00103   $more_headers .= "Message-Id: <".$msg_id.">\n";
00104   # Add refs
00105   if ($savannah_artifact && $savannah_artifact_id)
00106     {      
00107       $more_headers .= "References: ".trackers_get_msgid($savannah_artifact, $savannah_artifact_id)."\n";
00108       $more_headers .= "In-Reply-To: ".trackers_get_msgid($savannah_artifact, $savannah_artifact_id, true)."\n";
00109     }
00110 
00111   # Add a signature for the server
00112   $message .= "\n\n_______________________________________________
00113   ".sprintf(_("Message sent via/by %s"), $GLOBALS['sys_name'])."
00114   http://".$GLOBALS['sys_default_domain'].$GLOBALS['sys_home']."\n";
00115 
00116   # Register the message id for future references
00117   if ($savannah_artifact && $savannah_artifact_id)
00118     {
00119       trackers_register_msgid($msg_id, $savannah_artifact, $savannah_artifact_id);
00120     }
00121 
00122   # If there's an exclude list, create an array 
00123   # Convert ; into
00124   $exclude = array();
00125   if ($exclude_list)
00126     {
00127       $exclude_list = ereg_replace(";", ",", $exclude_list);
00128        $exclude = array_unique(explode(",", ereg_replace(" ", "", $exclude_list)));
00129     }
00130 
00131   while (list(,$v) = each($exclude)) 
00132     {
00133        if ($v)
00134          { $exclude[$v] = 1;  }
00135     }
00136 
00137 
00138   # Forge the real to list, by parsing every item of the $to list
00139   unset($real_to);
00140   $list = array();
00141   $user_subject = array();
00142   $user_name  = array();
00143 
00144   while (list($k,$v) = each($to)) 
00145 
00146     {
00147       if (is_numeric($v)) {
00148         $touid = $v;
00149       } else {
00150         $touid = user_getid($v);
00151       }
00152       # Exists in the exclude array? Skip it
00153       if ($exclude[$v])
00154         { continue; }
00155 
00156       $i++;
00157       unset($skip);
00158       # If an address is a username, get the email address from
00159       # the database.
00160       # If nothing is found, just let the username - there's maybe a 
00161       # local alias.
00162       if (!ereg("@", $v)) 
00163         {
00164           if (user_exists($touid)) 
00165             { 
00166                 # Exists in the exclude array? Skip it
00167                if (is_array($exclude) && array_key_exists(user_getname($touid), $exclude))
00168                   { continue; }
00169                 # Does the user have a specific subject line?
00170                 if (user_get_preference("subject_line", $touid) != "")
00171                   {
00172                      $list[$i] = $v;
00173                      $user_subject[$v] = sendmail_format_subject_line(user_get_preference("subject_line", $touid), $savannah_project, $savannah_artifact, $savannah_artifact_id)." ".$subject;
00174                      $user_name[$v] = user_getrealname($touid, 1)." <".user_getemail($touid).">";
00175                      $skip = 1;
00176                   }
00177 
00178                 $v = user_getrealname($touid, 1)." <".user_getemail($touid).">"; 
00179 
00180             }
00181         }
00182     # If $v is set, add it to the list, 
00183     # unless user want a specific subject line
00184     if (!$skip)
00185       { 
00186         $real_to .= $v.", "; 
00187       }
00188 
00189     } 
00190 
00191   # Add eventually info on the subject
00192   if ($savannah_artifact && $savannah_artifact_id) 
00193     { 
00194        $subject = "[".utils_get_tracker_prefix($savannah_artifact)." #".$savannah_artifact_id."] ".$subject; 
00195     }
00196  
00197    # Remove the extra ", " at the end of the list
00198    $real_to = substr($real_to,0,-2);
00199 
00200    # Beuc - 20050316
00201    # That's what I intended to do:
00202 
00203    # All newlines should be \r\n; this is apparently more
00204    # RFC821-compliant.
00205    # $message = preg_replace("/(?<!\r)\n/", "\r\n", $message);
00206 
00207    # However the opposite is certainly more Mailman-compliant; a bug
00208    # report has been posted to the Mailman team - wait&see [bug #1980]
00209    $message = str_replace("\r\n", "\n", $message);
00210 
00211    # Send the mail in UTF-8.
00212    # Normally, nothing non-ASCII should be contained in To: field, apart the 
00213    # real names.
00214    if ($real_to) 
00215         {
00216           $ret .= mail(sendmail_encode_header_content($real_to), sendmail_encode_header_content($subject), $message, $more_headers);
00217           fb(sprintf(_("Mail sent to %s"), utils_email($real_to, 1)));
00218         } 
00219    
00220    # Send mails with specific subject line
00221    while (list(,$v) = each($list)) 
00222      {
00223         $ret .= mail(sendmail_encode_header_content($user_name[$v]), sendmail_encode_header_content($user_subject[$v]), $message, $more_headers);
00224         fb(sprintf(_("Mail sent to %s"), utils_email($user_name[$v], 1)));
00225      }  
00226       
00227   return $ret; 
00228 }
00229 
00230 
00231 # Needed to send utf-8 headers:
00232 # Take a look at http://www.faqs.org/rfcs/rfc2047.html
00233 # We should use mb_encode_mimeheader() but it just does not work.
00234 #
00235 # We must not encode starting and ending quotes.
00236 # We assume there could be only 2 quotes. Otherwise it would be a malformed
00237 # address.
00238 # The easy way we use to do this is to simply consider as one string the 
00239 # content of the quote, if any. If so, we are not working word per word but
00240 # it saves us the time of searching for quotes in every words.
00241 function sendmail_encode_header_content ($header, $charset="UTF-8")
00242 {
00243   if (ereg('"', $header)) 
00244    {
00245      # quotes found, we each quoted part will be a string to encode
00246      $words = split('"', $header);
00247      $withquotes = 1;
00248    }
00249   else 
00250    {
00251      # otherwise, the default behavior is to consider words as strings to 
00252      # encode
00253      $words = split(' ', $header);
00254    }
00255 
00256   while (list($key,$word) = each($words))
00257     {
00258       # Check word per word if they need encoding
00259       if (!utils_is_ascii($word)) {
00260          $words[$key] = "=?$charset?B?".base64_encode($word)."?=";
00261       }
00262     }
00263   
00264   if ($withquotes) 
00265    {
00266      return join('"', $words);
00267    }
00268   else
00269    {
00270      return join(' ', $words);
00271    }
00272 }
00273 
00274 
00275 # A form for logged in users to send mails to others users
00276 function sendmail_form_message ($form_action, $user_id) 
00277 {
00278   global $HTML;
00279   print $HTML->box_top(sprintf(_("Send a Message to %s"),user_getrealname($user_id)));
00280   print '<p class="warn">'.("If you are writing for help, did you read the project 
00281 documentation first? Try to provide any potentially useful information you can think of.").'</p>';
00282 
00283   # We do not really bother finding out the realname + email, sendmail_mail()
00284   # will do it.
00285   print '
00286  <form action="'.$form_action.'" method="post">
00287    <input type="hidden" name="touser" value="'.$user_id.'" />
00288    <input type="hidden" name="fromuser" value="'.user_getname().'" />
00289 
00290    <span class="preinput">'._("From:").'</span><br />&nbsp;&nbsp;&nbsp;'.user_getrealname(user_getid(), 1).' &lt;'.user_getemail(user_getid()).'&gt;<br />
00291     <span class="preinput">'._("Mailer:").'</span><br />&nbsp;&nbsp;&nbsp;'.utils_cutstring($GLOBALS['HTTP_USER_AGENT'], "50").'<br />
00292    <span class="preinput">'._("Subject:").'</span><br />&nbsp;&nbsp;&nbsp;<input type="text" name="subject" size="60" maxlength="45" value="" /><br />
00293    <span class="preinput">'._("Message:").'</span><br />
00294    &nbsp;&nbsp;&nbsp;<textarea name="body" rows="20" cols="60"></textarea>
00295 
00296    <p align="center"><input type="submit" name="send_mail" value="Send Message" /></p>
00297 </form>';
00298   print $HTML->box_bottom();
00299 }
00300 
00301 function sendmail_format_subject_line ($subject_line, $savannah_project="", $savannah_artifact="", $savannah_artifact_id="") 
00302 {
00303 
00304   $subject_line = ereg_replace("%SERVER", $GLOBALS['sys_default_domain'], $subject_line);
00305   $subject_line = ereg_replace("%PROJECT", $savannah_project, $subject_line);
00306   $subject_line = ereg_replace("%TRACKER", $savannah_artifact, $subject_line);
00307   return ereg_replace("%ITEM", "#".$savannah_artifact_id, $subject_line);
00308 }
00309 
00310 function sendmail_create_msgid ()
00311 {
00312   mt_srand((double)microtime()*1000000);
00313   return date("Ymd-His", time()).".sv".user_getid().".".mt_rand(0,100000)."@".$_SERVER["HTTP_HOST"];
00314 }
00315 
00316 ?>

Generated on Sun Feb 26 13:23:04 2006 for Savane PHP Frontend Developer Reference by  doxygen 1.4.4