1bb01c27cSAndreas Gohr<?php 2bb01c27cSAndreas Gohr/** 3*1d045709SAndreas Gohr * A class to build and send multi part mails (with HTML content and embedded 4*1d045709SAndreas Gohr * attachments). All mails are assumed to be in UTF-8 encoding. 5*1d045709SAndreas Gohr * 6*1d045709SAndreas Gohr * Attachments are handled in memory so this shouldn't be used to send huge 7*1d045709SAndreas Gohr * files, but then again mail shouldn't be used to send huge files either. 8*1d045709SAndreas Gohr * 9bb01c27cSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 10bb01c27cSAndreas Gohr */ 11bb01c27cSAndreas Gohr 12bb01c27cSAndreas Gohr// end of line for mail lines - RFC822 says CRLF but postfix (and other MTAs?) 13bb01c27cSAndreas Gohr// think different 14bb01c27cSAndreas Gohrif(!defined('MAILHEADER_EOL')) define('MAILHEADER_EOL',"\n"); 15bb01c27cSAndreas Gohr#define('MAILHEADER_ASCIIONLY',1); 16bb01c27cSAndreas Gohr 17bb01c27cSAndreas Gohrclass Mailer { 18bb01c27cSAndreas Gohr 19bb01c27cSAndreas Gohr private $headers = array(); 20bb01c27cSAndreas Gohr private $attach = array(); 21bb01c27cSAndreas Gohr private $html = ''; 22bb01c27cSAndreas Gohr private $text = ''; 23bb01c27cSAndreas Gohr 24bb01c27cSAndreas Gohr private $boundary = ''; 25bb01c27cSAndreas Gohr private $partid = ''; 26*1d045709SAndreas Gohr private $sendparam= null; 27bb01c27cSAndreas Gohr 28*1d045709SAndreas Gohr private $validator = null; 29*1d045709SAndreas Gohr 30*1d045709SAndreas Gohr /** 31*1d045709SAndreas Gohr * Constructor 32*1d045709SAndreas Gohr * 33*1d045709SAndreas Gohr * Initializes the boundary strings and part counters 34*1d045709SAndreas Gohr */ 35*1d045709SAndreas Gohr public function __construct(){ 36*1d045709SAndreas Gohr if(isset($_SERVER['SERVER_NAME'])){ 37*1d045709SAndreas Gohr $server = $_SERVER['SERVER_NAME']; 38*1d045709SAndreas Gohr }else{ 39*1d045709SAndreas Gohr $server = 'localhost'; 40*1d045709SAndreas Gohr } 41*1d045709SAndreas Gohr 42*1d045709SAndreas Gohr $this->partid = md5(uniqid(rand(),true)).'@'.$server; 43bb01c27cSAndreas Gohr $this->boundary = '----------'.md5(uniqid(rand(),true)); 44bb01c27cSAndreas Gohr } 45bb01c27cSAndreas Gohr 46bb01c27cSAndreas Gohr /** 47bb01c27cSAndreas Gohr * Attach a file 48bb01c27cSAndreas Gohr * 49bb01c27cSAndreas Gohr * @param $path Path to the file to attach 50bb01c27cSAndreas Gohr * @param $mime Mimetype of the attached file 51bb01c27cSAndreas Gohr * @param $name The filename to use 52bb01c27cSAndreas Gohr * @param $embed Unique key to reference this file from the HTML part 53bb01c27cSAndreas Gohr */ 54bb01c27cSAndreas Gohr public function attachFile($path,$mime,$name='',$embed=''){ 55bb01c27cSAndreas Gohr if(!$name){ 56bb01c27cSAndreas Gohr $name = basename($path); 57bb01c27cSAndreas Gohr } 58bb01c27cSAndreas Gohr 59bb01c27cSAndreas Gohr $this->attach[] = array( 60bb01c27cSAndreas Gohr 'data' => file_get_contents($path), 61bb01c27cSAndreas Gohr 'mime' => $mime, 62bb01c27cSAndreas Gohr 'name' => $name, 63bb01c27cSAndreas Gohr 'embed' => $embed 64bb01c27cSAndreas Gohr ); 65bb01c27cSAndreas Gohr } 66bb01c27cSAndreas Gohr 67bb01c27cSAndreas Gohr /** 68bb01c27cSAndreas Gohr * Attach a file 69bb01c27cSAndreas Gohr * 70bb01c27cSAndreas Gohr * @param $path The file contents to attach 71bb01c27cSAndreas Gohr * @param $mime Mimetype of the attached file 72bb01c27cSAndreas Gohr * @param $name The filename to use 73bb01c27cSAndreas Gohr * @param $embed Unique key to reference this file from the HTML part 74bb01c27cSAndreas Gohr */ 75bb01c27cSAndreas Gohr public function attachContent($data,$mime,$name='',$embed=''){ 76bb01c27cSAndreas Gohr if(!$name){ 77bb01c27cSAndreas Gohr list($junk,$ext) = split('/',$mime); 78bb01c27cSAndreas Gohr $name = count($this->attach).".$ext"; 79bb01c27cSAndreas Gohr } 80bb01c27cSAndreas Gohr 81bb01c27cSAndreas Gohr $this->attach[] = array( 82bb01c27cSAndreas Gohr 'data' => $data, 83bb01c27cSAndreas Gohr 'mime' => $mime, 84bb01c27cSAndreas Gohr 'name' => $name, 85bb01c27cSAndreas Gohr 'embed' => $embed 86bb01c27cSAndreas Gohr ); 87bb01c27cSAndreas Gohr } 88bb01c27cSAndreas Gohr 89bb01c27cSAndreas Gohr /** 90*1d045709SAndreas Gohr * Add an arbitrary header to the mail 91*1d045709SAndreas Gohr * 92*1d045709SAndreas Gohr * @param string $header the header name (no trailing colon!) 93*1d045709SAndreas Gohr * @param string $value the value of the header 94*1d045709SAndreas Gohr * @param bool $clean remove all non-ASCII chars and line feeds? 95*1d045709SAndreas Gohr */ 96*1d045709SAndreas Gohr public function setHeader($header,$value,$clean=true){ 97*1d045709SAndreas Gohr $header = ucwords(strtolower($header)); // streamline casing 98*1d045709SAndreas Gohr if($clean){ 99*1d045709SAndreas Gohr $header = preg_replace('/[^\w \-\.\+\@]+/','',$header); 100*1d045709SAndreas Gohr $value = preg_replace('/[^\w \-\.\+\@]+/','',$value); 101*1d045709SAndreas Gohr } 102*1d045709SAndreas Gohr $this->headers[$header] = $value; 103*1d045709SAndreas Gohr } 104*1d045709SAndreas Gohr 105*1d045709SAndreas Gohr /** 106*1d045709SAndreas Gohr * Set additional parameters to be passed to sendmail 107*1d045709SAndreas Gohr * 108*1d045709SAndreas Gohr * Whatever is set here is directly passed to PHP's mail() command as last 109*1d045709SAndreas Gohr * parameter. Depending on the PHP setup this might break mailing alltogether 110*1d045709SAndreas Gohr */ 111*1d045709SAndreas Gohr public function setParameters($param){ 112*1d045709SAndreas Gohr $this->sendparam = $param; 113*1d045709SAndreas Gohr } 114*1d045709SAndreas Gohr 115*1d045709SAndreas Gohr /** 116bb01c27cSAndreas Gohr * Set the HTML part of the mail 117bb01c27cSAndreas Gohr * 118bb01c27cSAndreas Gohr * Placeholders can be used to reference embedded attachments 119bb01c27cSAndreas Gohr */ 120*1d045709SAndreas Gohr public function setHTML($html){ 121bb01c27cSAndreas Gohr $this->html = $html; 122bb01c27cSAndreas Gohr } 123bb01c27cSAndreas Gohr 124bb01c27cSAndreas Gohr /** 125bb01c27cSAndreas Gohr * Set the plain text part of the mail 126bb01c27cSAndreas Gohr */ 127*1d045709SAndreas Gohr public function setText($text){ 128bb01c27cSAndreas Gohr $this->text = $text; 129bb01c27cSAndreas Gohr } 130bb01c27cSAndreas Gohr 131bb01c27cSAndreas Gohr /** 132*1d045709SAndreas Gohr * Sets an email address header with correct encoding 133bb01c27cSAndreas Gohr * 134bb01c27cSAndreas Gohr * Unicode characters will be deaccented and encoded base64 135bb01c27cSAndreas Gohr * for headers. Addresses may not contain Non-ASCII data! 136bb01c27cSAndreas Gohr * 137bb01c27cSAndreas Gohr * Example: 138bb01c27cSAndreas Gohr * setAddress("föö <foo@bar.com>, me@somewhere.com","TBcc"); 139bb01c27cSAndreas Gohr * 140bb01c27cSAndreas Gohr * @param string $address Multiple adresses separated by commas 141bb01c27cSAndreas Gohr * @param string $header Name of the header (To,Bcc,Cc,...) 142bb01c27cSAndreas Gohr */ 143*1d045709SAndreas Gohr function setAddress($address,$header){ 144bb01c27cSAndreas Gohr // No named recipients for To: in Windows (see FS#652) 145bb01c27cSAndreas Gohr $names = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? false : true; 146bb01c27cSAndreas Gohr 147*1d045709SAndreas Gohr $header = ucwords(strtolower($header)); // streamline casing 148*1d045709SAndreas Gohr $address = preg_replace('/[\r\n\0]+/',' ',$address); // remove attack vectors 149*1d045709SAndreas Gohr 150bb01c27cSAndreas Gohr $headers = ''; 151bb01c27cSAndreas Gohr $parts = explode(',',$address); 152bb01c27cSAndreas Gohr foreach ($parts as $part){ 153bb01c27cSAndreas Gohr $part = trim($part); 154bb01c27cSAndreas Gohr 155bb01c27cSAndreas Gohr // parse address 156bb01c27cSAndreas Gohr if(preg_match('#(.*?)<(.*?)>#',$part,$matches)){ 157bb01c27cSAndreas Gohr $text = trim($matches[1]); 158bb01c27cSAndreas Gohr $addr = $matches[2]; 159bb01c27cSAndreas Gohr }else{ 160bb01c27cSAndreas Gohr $addr = $part; 161bb01c27cSAndreas Gohr } 162bb01c27cSAndreas Gohr // skip empty ones 163bb01c27cSAndreas Gohr if(empty($addr)){ 164bb01c27cSAndreas Gohr continue; 165bb01c27cSAndreas Gohr } 166bb01c27cSAndreas Gohr 167bb01c27cSAndreas Gohr // FIXME: is there a way to encode the localpart of a emailaddress? 168bb01c27cSAndreas Gohr if(!utf8_isASCII($addr)){ 169bb01c27cSAndreas Gohr msg(htmlspecialchars("E-Mail address <$addr> is not ASCII"),-1); 170bb01c27cSAndreas Gohr continue; 171bb01c27cSAndreas Gohr } 172bb01c27cSAndreas Gohr 173*1d045709SAndreas Gohr if(is_null($this->validator)){ 174*1d045709SAndreas Gohr $this->validator = new EmailAddressValidator(); 175*1d045709SAndreas Gohr $this->validator->allowLocalAddresses = true; 176*1d045709SAndreas Gohr } 177*1d045709SAndreas Gohr if(!$this->validator->check_email_address($addr)){ 178bb01c27cSAndreas Gohr msg(htmlspecialchars("E-Mail address <$addr> is not valid"),-1); 179bb01c27cSAndreas Gohr continue; 180bb01c27cSAndreas Gohr } 181bb01c27cSAndreas Gohr 182bb01c27cSAndreas Gohr // text was given 183bb01c27cSAndreas Gohr if(!empty($text) && $names){ 184bb01c27cSAndreas Gohr // add address quotes 185bb01c27cSAndreas Gohr $addr = "<$addr>"; 186bb01c27cSAndreas Gohr 187bb01c27cSAndreas Gohr if(defined('MAILHEADER_ASCIIONLY')){ 188bb01c27cSAndreas Gohr $text = utf8_deaccent($text); 189bb01c27cSAndreas Gohr $text = utf8_strip($text); 190bb01c27cSAndreas Gohr } 191bb01c27cSAndreas Gohr 192bb01c27cSAndreas Gohr if(!utf8_isASCII($text)){ 193*1d045709SAndreas Gohr //FIXME check if this is needed for base64 too 194bb01c27cSAndreas Gohr // put the quotes outside as in =?UTF-8?Q?"Elan Ruusam=C3=A4e"?= vs "=?UTF-8?Q?Elan Ruusam=C3=A4e?=" 195bb01c27cSAndreas Gohr /* 196bb01c27cSAndreas Gohr if (preg_match('/^"(.+)"$/', $text, $matches)) { 197bb01c27cSAndreas Gohr $text = '"=?UTF-8?Q?'.mail_quotedprintable_encode($matches[1], 0).'?="'; 198bb01c27cSAndreas Gohr } else { 199bb01c27cSAndreas Gohr $text = '=?UTF-8?Q?'.mail_quotedprintable_encode($text, 0).'?='; 200bb01c27cSAndreas Gohr } 201bb01c27cSAndreas Gohr */ 202bb01c27cSAndreas Gohr $text = '=?UTF-8?B?'.base64_encode($text).'?='; 203bb01c27cSAndreas Gohr } 204bb01c27cSAndreas Gohr }else{ 205bb01c27cSAndreas Gohr $text = ''; 206bb01c27cSAndreas Gohr } 207bb01c27cSAndreas Gohr 208bb01c27cSAndreas Gohr // add to header comma seperated 209bb01c27cSAndreas Gohr if($headers != ''){ 210bb01c27cSAndreas Gohr $headers .= ','; 211bb01c27cSAndreas Gohr $headers .= MAILHEADER_EOL.' '; // avoid overlong mail headers 212bb01c27cSAndreas Gohr } 213bb01c27cSAndreas Gohr $headers .= $text.' '.$addr; 214bb01c27cSAndreas Gohr } 215bb01c27cSAndreas Gohr 216bb01c27cSAndreas Gohr if(empty($headers)) return false; 217bb01c27cSAndreas Gohr 218bb01c27cSAndreas Gohr $this->headers[$header] = $headers; 219bb01c27cSAndreas Gohr return $headers; 220bb01c27cSAndreas Gohr } 221bb01c27cSAndreas Gohr 222bb01c27cSAndreas Gohr /** 223bb01c27cSAndreas Gohr * Add the To: recipients 224bb01c27cSAndreas Gohr * 225bb01c27cSAndreas Gohr * @see setAddress 226bb01c27cSAndreas Gohr * @param string $address Multiple adresses separated by commas 227bb01c27cSAndreas Gohr */ 228bb01c27cSAndreas Gohr public function to($address){ 229bb01c27cSAndreas Gohr $this->setAddress($address, 'To'); 230bb01c27cSAndreas Gohr } 231bb01c27cSAndreas Gohr 232bb01c27cSAndreas Gohr /** 233bb01c27cSAndreas Gohr * Add the Cc: recipients 234bb01c27cSAndreas Gohr * 235bb01c27cSAndreas Gohr * @see setAddress 236bb01c27cSAndreas Gohr * @param string $address Multiple adresses separated by commas 237bb01c27cSAndreas Gohr */ 238bb01c27cSAndreas Gohr public function cc($address){ 239bb01c27cSAndreas Gohr $this->setAddress($address, 'Cc'); 240bb01c27cSAndreas Gohr } 241bb01c27cSAndreas Gohr 242bb01c27cSAndreas Gohr /** 243bb01c27cSAndreas Gohr * Add the Bcc: recipients 244bb01c27cSAndreas Gohr * 245bb01c27cSAndreas Gohr * @see setAddress 246bb01c27cSAndreas Gohr * @param string $address Multiple adresses separated by commas 247bb01c27cSAndreas Gohr */ 248bb01c27cSAndreas Gohr public function bcc($address){ 249bb01c27cSAndreas Gohr $this->setAddress($address, 'Bcc'); 250bb01c27cSAndreas Gohr } 251bb01c27cSAndreas Gohr 252bb01c27cSAndreas Gohr /** 253*1d045709SAndreas Gohr * Add the From: address 254*1d045709SAndreas Gohr * 255*1d045709SAndreas Gohr * This is set to $conf['mailfrom'] when not specified so you shouldn't need 256*1d045709SAndreas Gohr * to call this function 257*1d045709SAndreas Gohr * 258*1d045709SAndreas Gohr * @see setAddress 259*1d045709SAndreas Gohr * @param string $address from address 260*1d045709SAndreas Gohr */ 261*1d045709SAndreas Gohr public function from($address){ 262*1d045709SAndreas Gohr $this->setAddress($address, 'From'); 263*1d045709SAndreas Gohr } 264*1d045709SAndreas Gohr 265*1d045709SAndreas Gohr /** 266bb01c27cSAndreas Gohr * Add the mail's Subject: header 267bb01c27cSAndreas Gohr * 268bb01c27cSAndreas Gohr * @param string $subject the mail subject 269bb01c27cSAndreas Gohr */ 270bb01c27cSAndreas Gohr public function subject($subject){ 271bb01c27cSAndreas Gohr if(!utf8_isASCII($subject)){ 272bb01c27cSAndreas Gohr $subject = '=?UTF-8?B?'.base64_encode($subject).'?='; 273bb01c27cSAndreas Gohr } 274bb01c27cSAndreas Gohr $this->headers['Subject'] = $subject; 275bb01c27cSAndreas Gohr } 276bb01c27cSAndreas Gohr 277bb01c27cSAndreas Gohr /** 278bb01c27cSAndreas Gohr * Prepare the mime multiparts for all attachments 279bb01c27cSAndreas Gohr * 280bb01c27cSAndreas Gohr * Replaces placeholders in the HTML with the correct CIDs 281bb01c27cSAndreas Gohr */ 282bb01c27cSAndreas Gohr protected function prepareAttachments(){ 283bb01c27cSAndreas Gohr $mime = ''; 284bb01c27cSAndreas Gohr $part = 1; 285bb01c27cSAndreas Gohr // embedded attachments 286bb01c27cSAndreas Gohr foreach($this->attach as $media){ 287bb01c27cSAndreas Gohr // create content id 288bb01c27cSAndreas Gohr $cid = 'part'.$part.'.'.$this->partid; 289bb01c27cSAndreas Gohr 290bb01c27cSAndreas Gohr // replace wildcards 291bb01c27cSAndreas Gohr if($media['embed']){ 292bb01c27cSAndreas Gohr $this->html = str_replace('%%'.$media['embed'].'%%','cid:'.$cid,$this->html); 293bb01c27cSAndreas Gohr } 294bb01c27cSAndreas Gohr 295bb01c27cSAndreas Gohr $mime .= '--'.$this->boundary.MAILHEADER_EOL; 296bb01c27cSAndreas Gohr $mime .= 'Content-Type: '.$media['mime'].';'.MAILHEADER_EOL; 297bb01c27cSAndreas Gohr $mime .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL; 298bb01c27cSAndreas Gohr $mime .= "Content-ID: <$cid>".MAILHEADER_EOL; 299bb01c27cSAndreas Gohr if($media['embed']){ 300bb01c27cSAndreas Gohr $mime .= 'Content-Disposition: inline; filename="'.$media['name'].'"'.MAILHEADER_EOL; 301bb01c27cSAndreas Gohr }else{ 302bb01c27cSAndreas Gohr $mime .= 'Content-Disposition: attachment; filename="'.$media['name'].'"'.MAILHEADER_EOL; 303bb01c27cSAndreas Gohr } 304bb01c27cSAndreas Gohr $mime .= MAILHEADER_EOL; //end of headers 305bb01c27cSAndreas Gohr $mime .= chunk_split(base64_encode($media['data']),74,MAILHEADER_EOL); 306bb01c27cSAndreas Gohr 307bb01c27cSAndreas Gohr $part++; 308bb01c27cSAndreas Gohr } 309bb01c27cSAndreas Gohr return $mime; 310bb01c27cSAndreas Gohr } 311bb01c27cSAndreas Gohr 312*1d045709SAndreas Gohr /** 313*1d045709SAndreas Gohr * Build the body and handles multi part mails 314*1d045709SAndreas Gohr * 315*1d045709SAndreas Gohr * Needs to be called before prepareHeaders! 316*1d045709SAndreas Gohr * 317*1d045709SAndreas Gohr * @return string the prepared mail body, false on errors 318*1d045709SAndreas Gohr */ 319*1d045709SAndreas Gohr protected function prepareBody(){ 320*1d045709SAndreas Gohr global $conf; 321*1d045709SAndreas Gohr 322bb01c27cSAndreas Gohr // check for body 323bb01c27cSAndreas Gohr if(!$this->text && !$this->html){ 324bb01c27cSAndreas Gohr return false; 325bb01c27cSAndreas Gohr } 326bb01c27cSAndreas Gohr 327bb01c27cSAndreas Gohr // add general headers 328*1d045709SAndreas Gohr if(!isset($this->headers['From'])) $this->from($conf['mailfrom']); 329bb01c27cSAndreas Gohr $this->headers['MIME-Version'] = '1.0'; 330bb01c27cSAndreas Gohr 331*1d045709SAndreas Gohr $body = ''; 332*1d045709SAndreas Gohr 333bb01c27cSAndreas Gohr if(!$this->html && !count($this->attach)){ // we can send a simple single part message 334bb01c27cSAndreas Gohr $this->headers['Content-Type'] = 'text/plain; charset=UTF-8'; 335bb01c27cSAndreas Gohr $this->headers['Content-Transfer-Encoding'] = 'base64'; 336*1d045709SAndreas Gohr $body .= chunk_split(base64_encode($this->text),74,MAILHEADER_EOL); 337bb01c27cSAndreas Gohr }else{ // multi part it is 338*1d045709SAndreas Gohr $body .= "This is a multi-part message in MIME format.".MAILHEADER_EOL; 339bb01c27cSAndreas Gohr 340bb01c27cSAndreas Gohr // prepare the attachments 341bb01c27cSAndreas Gohr $attachments = $this->prepareAttachments(); 342bb01c27cSAndreas Gohr 343bb01c27cSAndreas Gohr // do we have alternative text content? 344bb01c27cSAndreas Gohr if($this->text && $this->html){ 345bb01c27cSAndreas Gohr $this->headers['Content-Type'] = 'multipart/alternative; boundary="'.$this->boundary.'XX"'; 346bb01c27cSAndreas Gohr $body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL; 347*1d045709SAndreas Gohr $body .= 'Content-Type: text/plain; charset=UTF-8'.MAILHEADER_EOL; 348*1d045709SAndreas Gohr $body .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL; 349bb01c27cSAndreas Gohr $body .= MAILHEADER_EOL; 350bb01c27cSAndreas Gohr $body .= chunk_split(base64_encode($this->text),74,MAILHEADER_EOL); 351bb01c27cSAndreas Gohr $body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL; 352bb01c27cSAndreas Gohr $body .= 'Content-Type: multipart/related; boundary="'.$this->boundary.'"'.MAILHEADER_EOL; 353bb01c27cSAndreas Gohr $body .= MAILHEADER_EOL; 354bb01c27cSAndreas Gohr } 355bb01c27cSAndreas Gohr 356*1d045709SAndreas Gohr $body .= '--'.$this->boundary.MAILHEADER_EOL; 357*1d045709SAndreas Gohr $body .= 'Content-Type: text/html; charset=UTF-8'.MAILHEADER_EOL; 358*1d045709SAndreas Gohr $body .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL; 359bb01c27cSAndreas Gohr $body .= MAILHEADER_EOL; 360*1d045709SAndreas Gohr $body .= chunk_split(base64_encode($this->html),74,MAILHEADER_EOL); 361bb01c27cSAndreas Gohr $body .= MAILHEADER_EOL; 362bb01c27cSAndreas Gohr $body .= $attachments; 363bb01c27cSAndreas Gohr $body .= '--'.$this->boundary.'--'.MAILHEADER_EOL; 364bb01c27cSAndreas Gohr 365bb01c27cSAndreas Gohr // close open multipart/alternative boundary 366bb01c27cSAndreas Gohr if($this->text && $this->html){ 367bb01c27cSAndreas Gohr $body .= '--'.$this->boundary.'XX--'.MAILHEADER_EOL; 368bb01c27cSAndreas Gohr } 369bb01c27cSAndreas Gohr } 370bb01c27cSAndreas Gohr 371bb01c27cSAndreas Gohr return $body; 372bb01c27cSAndreas Gohr } 373bb01c27cSAndreas Gohr 374bb01c27cSAndreas Gohr /** 375bb01c27cSAndreas Gohr * Create a string from the headers array 376*1d045709SAndreas Gohr * 377*1d045709SAndreas Gohr * @returns string the headers 378bb01c27cSAndreas Gohr */ 379bb01c27cSAndreas Gohr protected function prepareHeaders(){ 380bb01c27cSAndreas Gohr $headers = ''; 381bb01c27cSAndreas Gohr foreach($this->headers as $key => $val){ 382bb01c27cSAndreas Gohr $headers .= "$key: $val".MAILHEADER_EOL; 383bb01c27cSAndreas Gohr } 384bb01c27cSAndreas Gohr return $headers; 385bb01c27cSAndreas Gohr } 386bb01c27cSAndreas Gohr 387bb01c27cSAndreas Gohr /** 388bb01c27cSAndreas Gohr * return a full email with all headers 389bb01c27cSAndreas Gohr * 390*1d045709SAndreas Gohr * This is mainly intended for debugging and testing but could also be 391*1d045709SAndreas Gohr * used for MHT exports 392*1d045709SAndreas Gohr * 393*1d045709SAndreas Gohr * @return string the mail, false on errors 394bb01c27cSAndreas Gohr */ 395bb01c27cSAndreas Gohr public function dump(){ 396bb01c27cSAndreas Gohr $body = $this->prepareBody(); 397*1d045709SAndreas Gohr if($body === 'false') return false; 398*1d045709SAndreas Gohr $headers = $this->prepareHeaders(); 399bb01c27cSAndreas Gohr 400bb01c27cSAndreas Gohr return $headers.MAILHEADER_EOL.$body; 401bb01c27cSAndreas Gohr } 402*1d045709SAndreas Gohr 403*1d045709SAndreas Gohr /** 404*1d045709SAndreas Gohr * Send the mail 405*1d045709SAndreas Gohr * 406*1d045709SAndreas Gohr * Call this after all data was set 407*1d045709SAndreas Gohr * 408*1d045709SAndreas Gohr * @fixme we need to support the old plugin hook here! 409*1d045709SAndreas Gohr * @return bool true if the mail was successfully passed to the MTA 410*1d045709SAndreas Gohr */ 411*1d045709SAndreas Gohr public function send(){ 412*1d045709SAndreas Gohr // any recipients? 413*1d045709SAndreas Gohr if(trim($this->headers['To']) === '' && 414*1d045709SAndreas Gohr trim($this->headers['Cc']) === '' && 415*1d045709SAndreas Gohr trim($this->headers['Bcc']) === '') return false; 416*1d045709SAndreas Gohr 417*1d045709SAndreas Gohr // The To: header is special 418*1d045709SAndreas Gohr if(isset($this->headers['To'])){ 419*1d045709SAndreas Gohr $to = $this->headers['To']; 420*1d045709SAndreas Gohr unset($this->headers['To']); 421*1d045709SAndreas Gohr }else{ 422*1d045709SAndreas Gohr $to = ''; 423*1d045709SAndreas Gohr } 424*1d045709SAndreas Gohr 425*1d045709SAndreas Gohr // so is the subject 426*1d045709SAndreas Gohr if(isset($this->headers['Subject'])){ 427*1d045709SAndreas Gohr $subject = $this->headers['Subject']; 428*1d045709SAndreas Gohr unset($this->headers['Subject']); 429*1d045709SAndreas Gohr }else{ 430*1d045709SAndreas Gohr $subject = ''; 431*1d045709SAndreas Gohr } 432*1d045709SAndreas Gohr 433*1d045709SAndreas Gohr // make the body 434*1d045709SAndreas Gohr $body = $this->prepareBody(); 435*1d045709SAndreas Gohr if($body === 'false') return false; 436*1d045709SAndreas Gohr 437*1d045709SAndreas Gohr // cook the headers 438*1d045709SAndreas Gohr $headers = $this->prepareHeaders(); 439*1d045709SAndreas Gohr 440*1d045709SAndreas Gohr // send the thing 441*1d045709SAndreas Gohr if(is_null($this->sendparam)){ 442*1d045709SAndreas Gohr return @mail($to,$subject,$body,$headers); 443*1d045709SAndreas Gohr }else{ 444*1d045709SAndreas Gohr return @mail($to,$subject,$body,$headers,$this->sendparam); 445*1d045709SAndreas Gohr } 446*1d045709SAndreas Gohr } 447bb01c27cSAndreas Gohr} 448