diff options
Diffstat (limited to 'inc')
-rw-r--r-- | inc/auth.php | 25 | ||||
-rw-r--r-- | inc/common.php | 6 | ||||
-rw-r--r-- | inc/mail.php | 176 | ||||
-rw-r--r-- | inc/utf8.php | 12 |
4 files changed, 196 insertions, 23 deletions
diff --git a/inc/auth.php b/inc/auth.php index 62e4fec32..0b4ed8113 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -12,6 +12,7 @@ require_once("inc/common.php"); require_once("inc/io.php"); require_once("inc/blowfish.php"); + require_once("inc/mail.php"); // load the the auth functions require_once('inc/auth_'.$conf['authtype'].'.php'); @@ -329,10 +330,10 @@ function auth_sendPassword($user,$password){ $text = str_replace('@PASSWORD@',$password,$text); $text = str_replace('@TITLE@',$conf['title'],$text); - if (!empty($conf['mailfrom'])) { - $hdrs = 'From: '.$conf['mailfrom']."\n"; - } - return @mail($userinfo['mail'],$lang['regpwmail'],$text,$hdrs); + return mail_send($userinfo['name'].' <'.$userinfo['mail'].'>', + $lang['regpwmail'], + $text, + $conf['mailfrom']); } /** @@ -366,7 +367,7 @@ function register(){ } //check mail - if(!isvalidemail($_POST['email'])){ + if(!mail_isvalid($_POST['email'])){ msg($lang['regbadmail'],-1); return false; } @@ -388,18 +389,4 @@ function register(){ } } -/** - * Uses a regular expresion to check if a given mail address is valid - * - * May not be completly RFC conform! - * - * @link http://www.webmasterworld.com/forum88/135.htm - * - * @param string $email the address to check - * @return bool true if address is valid - */ -function isvalidemail($email){ - return eregi("^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\\.[a-z]{2,4}$", $email); -} - ?> diff --git a/inc/common.php b/inc/common.php index 832352d3c..9b1c2900f 100644 --- a/inc/common.php +++ b/inc/common.php @@ -9,6 +9,7 @@ require_once("conf/dokuwiki.php"); require_once("inc/io.php"); require_once('inc/utf8.php'); + require_once('inc/mail.php'); //set up error reporting to sane values error_reporting(E_ALL ^ E_NOTICE); @@ -772,10 +773,7 @@ function notify($id,$rev="",$summary=""){ } $text = str_replace('@DIFF@',$diff,$text); - if (!empty($conf['mailfrom'])) { - $hdrs = 'From: '.$conf['mailfrom']."\n"; - } - @mail($conf['notify'],$subject,$text,$hdrs); + mail_send($conf['notify'],$subject,$text,$conf['mailfrom']); } /** diff --git a/inc/mail.php b/inc/mail.php new file mode 100644 index 000000000..b66678b02 --- /dev/null +++ b/inc/mail.php @@ -0,0 +1,176 @@ +<? +/** + * Mail functions + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Andreas Gohr <andi@splitbrain.org> + */ + +require_once('inc/utf8.php'); + +define('MAILHEADER_EOL',"\n"); //end of line for mail headers + +/** + * UTF-8 autoencoding replacement for PHPs mail function + * + * Email address fields (To, From, Cc, Bcc can contain a textpart and an address + * like this: 'Andreas Gohr <andi@splitbrain.org>' - the text part is encoded + * automatically. You can seperate receivers by commas. + * + * @todo currently an empty To: header is added + * + * @param string $to Receiver of the mail (multiple seperated by commas) + * @param string $subject Mailsubject + * @param string $body Messagebody + * @param string $from Sender address + * @param string $cc CarbonCopy receiver (multiple seperated by commas) + * @param string $bcc BlindCarbonCopy receiver (multiple seperated by commas) + * @param string $headers Additional Headers (seperated by MAILHEADER_EOL + * @param string $params Additonal Sendmail params (passed to mail()) + * + * @author Andreas Gohr <andi@splitbrain.org> + * @see mail() + */ +function mail_send($to, $subject, $body, $from='', $cc='', $bcc='', $headers=null, $params=null){ + if(!utf8_isASCII($subject)) $subject = '=?UTF-8?Q?'.mail_quotedprintable_encode($subject).'?='; + + $header = ''; + $header .= mail_encode_address($from,'From'); + $header .= mail_encode_address($to,'To'); + $header .= mail_encode_address($cc,'Cc'); + $header .= mail_encode_address($bcc,'Bcc'); + $header .= 'MIME-Version: 1.0'.MAILHEADER_EOL; + $header .= 'Content-Type: text/plain; charset=UTF-8'.MAILHEADER_EOL; + $header .= 'Content-Transfer-Encoding: quoted-printable'.MAILHEADER_EOL; + $header .= $headers; + $heade = trim($header); + + $body = mail_quotedprintable_encode($body); + + return @mail(null,$subject,$body,$header,$params); +} + +/** + * Encodes an email address header + * + * Unicode chracters will be encoded quoted_printable for headers like + * Addresses may not contain Non-ASCII data! + * + * Example: + * mail_encode_address("föö <foo@bar.com>, me@somewhere.com","To"); + * + * @param string $string Multiple headers seperated by commas + */ +function mail_encode_address($string,$header='To'){ + $headers = ''; + $parts = split(',',$string); + foreach ($parts as $part){ + $part = trim($part); + + // parse address + if(preg_match('#(.*?)<(.*?)>#',$part,$matches)){ + $text = trim($matches[1]); + $addr = $matches[2]; + }else{ + $addr = $part; + } + + // skip empty ones + if(empty($addr)){ + continue; + } + + // FIXME: is there a way to encode the localpart of a emailaddress? + if(!utf8_isASCII($addr)){ + msg(htmlspecialchars("E-Mail address <$addr> is not ASCII"),-1); + continue; + } + + if(!mail_isvalid($addr)){ + msg(htmlspecialchars("E-Mail address <$addr> is not valid"),-1); + continue; + } + + // no text was given + if(empty($text)){ + $headers .= $header.': <'.$addr.'>'.MAILHEADER_EOL; + continue; + } + + // FIME: can make problems with long headers? + if(!utf8_isASCII($text)){ + $text = '=?UTF-8?Q?'.mail_quotedprintable_encode($text).'?='; + } + + //construct header + $headers .= $header.': '.$text.' <'.$addr.'>'.MAILHEADER_EOL; + } + + return $headers; +} + +/** + * Uses a regular expresion to check if a given mail address is valid + * + * May not be completly RFC conform! + * + * @link http://www.webmasterworld.com/forum88/135.htm + * + * @param string $email the address to check + * @return bool true if address is valid + */ +function mail_isvalid($email){ + return eregi("^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\\.[a-z]{2,4}$", $email); +} + +/** + * Quoted printable encoding + * + * @author <pob@medienrecht.org> + * @author <tamas.tompa@kirowski.com> + * @link http://www.php.net/manual/en/function.quoted-printable-decode.php + */ +function mail_quotedprintable_encode($input='',$line_max=74,$space_conv=false){ + $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); + $lines = preg_split("/(?:\r\n|\r|\n)/", $input); + $eol = "\n"; + $escape = "="; + $output = ""; + while( list(, $line) = each($lines) ) { + //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary + $linlen = strlen($line); + $newline = ""; + for($i = 0; $i < $linlen; $i++) { + $c = substr( $line, $i, 1 ); + $dec = ord( $c ); + if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E + $c = "=2E"; + } + if ( $dec == 32 ) { + if ( $i == ( $linlen - 1 ) ) { // convert space at eol only + $c = "=20"; + } else if ( $space_conv ) { + $c = "=20"; + } + } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required + $h2 = floor($dec/16); + $h1 = floor($dec%16); + $c = $escape.$hex["$h2"].$hex["$h1"]; + } + if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted + $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay + $newline = ""; + // check if newline first character will be point or not + if ( $dec == 46 ) { + $c = "=2E"; + } + } + $newline .= $c; + } // end of for + $output .= $newline.$eol; + } // end of while + return trim($output); +} + + +?> diff --git a/inc/utf8.php b/inc/utf8.php index 1d2676688..bd52a7cf2 100644 --- a/inc/utf8.php +++ b/inc/utf8.php @@ -42,6 +42,18 @@ function utf8_decodeFN($file){ } /** + * Checks if a string contains 7bit ASCII only + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function utf8_isASCII($str){ + for($i=0; $i<strlen($str); $i++){ + if(ord($str{$i}) >127) return false; + } + return true; +} + +/** * Tries to detect if a string is in Unicode encoding * * @author <bmorel@ssi.fr> |