dolibarr  7.0.0-beta
CMailFile.class.php
Go to the documentation of this file.
1 <?php
37 class CMailFile
38 {
39  public $sendcontext;
40  public $sendmode;
41  public $sendsetup;
42 
43  var $subject; // Topic: Subject of email
44  var $addr_from; // From: Label and EMail of sender (must include '<>'). For example '<myemail@example.com>' or 'John Doe <myemail@example.com>' or '<myemail+trackingid@example.com>'). Note that with gmail smtps, value here is forced by google to account (but not the reply-to).
45  // Sender: Who send the email ("Sender" has sent emails on behalf of "From").
46  // Use it when the "From" is an email of a domain that is a SPF protected domain, and sending smtp server is not this domain. In such case, add Sender field with an email of the protected domain.
47  // Return-Path: Email where to send bounds.
48  var $reply_to; // Reply-To: Email where to send replies from mailer software (mailer use From if reply-to not defined, Gmail use gmail account if reply-to not defined)
49  var $errors_to; // Errors-To: Email where to send errors.
50  var $addr_to;
51  var $addr_cc;
52  var $addr_bcc;
53  var $trackid;
54 
55  var $mixed_boundary;
56  var $related_boundary;
57  var $alternative_boundary;
58  var $deliveryreceipt;
59 
60  var $eol;
61  var $eol2;
62  var $error='';
63 
64  var $smtps; // Contains SMTPs object (if this method is used)
65  var $phpmailer; // Contains PHPMailer object (if this method is used)
66 
67  //CSS
68  var $css;
70  var $styleCSS;
72  var $bodyCSS;
73 
74  var $headers;
75  var $message;
76 
77  // Image
78  var $html;
79  var $image_boundary;
80  var $atleastoneimage=0; // at least one image file with file=xxx.ext into content (TODO Debug this. How can this case be tested. Remove if not used).
81  var $html_images=array();
82  var $images_encoded=array();
83  var $image_types = array('gif' => 'image/gif',
84  'jpg' => 'image/jpeg',
85  'jpeg' => 'image/jpeg',
86  'jpe' => 'image/jpeg',
87  'bmp' => 'image/bmp',
88  'png' => 'image/png',
89  'tif' => 'image/tiff',
90  'tiff' => 'image/tiff');
91 
92 
113  function __construct($subject,$to,$from,$msg,$filename_list=array(),$mimetype_list=array(),$mimefilename_list=array(),$addr_cc="",$addr_bcc="",$deliveryreceipt=0,$msgishtml=0,$errors_to='',$css='',$trackid='',$moreinheader='',$sendcontext='standard')
114  {
115  global $conf, $dolibarr_main_data_root;
116 
117  $this->sendcontext = $sendcontext;
118 
119  // Define this->sendmode
120  $this->sendmode = '';
121  if ($this->sendcontext == 'emailing' && !empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'default')
122  {
123  $this->sendmode = $conf->global->MAIN_MAIL_SENDMODE_EMAILING;
124  }
125  if (empty($this->sendmode)) $this->sendmode=$conf->global->MAIN_MAIL_SENDMODE;
126  if (empty($this->sendmode)) $this->sendmode='mail';
127 
128  // We define end of line (RFC 821).
129  $this->eol="\r\n";
130  // We define end of line for header fields (RFC 822bis section 2.3 says header must contains \r\n).
131  $this->eol2="\r\n";
132  if (! empty($conf->global->MAIN_FIX_FOR_BUGGED_MTA))
133  {
134  $this->eol="\n";
135  $this->eol2="\n";
136  $moreinheader = str_replace("\r\n","\n",$moreinheader);
137  }
138 
139  // On defini mixed_boundary
140  $this->mixed_boundary = "multipart_x." . time() . ".x_boundary";
141 
142  // On defini related_boundary
143  $this->related_boundary = 'mul_'.dol_hash(uniqid("dolibarr2"), 3); // Force md5 hash (does not contains special chars)
144 
145  // On defini alternative_boundary
146  $this->alternative_boundary = 'mul_'.dol_hash(uniqid("dolibarr3"), 3); // Force md5 hash (does not contains special chars)
147 
148  dol_syslog("CMailFile::CMailfile: sendmode=".$this->sendmode." charset=".$conf->file->character_set_client." from=$from, to=$to, addr_cc=$addr_cc, addr_bcc=$addr_bcc, errors_to=$errors_to, trackid=$trackid sendcontext=$sendcontext", LOG_DEBUG);
149  dol_syslog("CMailFile::CMailfile: subject=".$subject.", deliveryreceipt=".$deliveryreceipt.", msgishtml=".$msgishtml, LOG_DEBUG);
150 
151  if (empty($subject))
152  {
153  dol_syslog("CMailFile::CMailfile: Try to send an email with empty subject");
154  $this->error='ErrorSubjectIsRequired';
155  return;
156  }
157  if (empty($msg))
158  {
159  dol_syslog("CMailFile::CMailfile: Try to send an email with empty body");
160  $msg='.'; // Avoid empty message (with empty message conten show a multipart structure)
161  }
162 
163  // Detect if message is HTML (use fast method)
164  if ($msgishtml == -1)
165  {
166  $this->msgishtml = 0;
167  if (dol_textishtml($msg)) $this->msgishtml = 1;
168  }
169  else
170  {
171  $this->msgishtml = $msgishtml;
172  }
173 
174  global $dolibarr_main_url_root;
175 
176  // Define $urlwithroot
177  $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
178  $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
179  //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
180 
181  // Replace relative /viewimage to absolute path
182  $msg = preg_replace('/src="'.preg_quote(DOL_URL_ROOT,'/').'\/viewimage\.php/ims', 'src="'.$urlwithroot.'/viewimage.php', $msg, -1, $nbrep);
183 
184  if (! empty($conf->global->MAIN_MAIL_FORCE_CONTENT_TYPE_TO_HTML)) $this->msgishtml=1; // To force to send everything with content type html.
185 
186  // Detect images
187  if ($this->msgishtml)
188  {
189  $this->html = $msg;
190 
191  if (! empty($conf->global->MAIN_MAIL_ADD_INLINE_IMAGES_IF_IN_MEDIAS))
192  {
193  $findimg = $this->findHtmlImages($dolibarr_main_data_root.'/medias');
194  }
195 
196  // Define if there is at least one file
197  if ($findimg)
198  {
199  foreach ($this->html_images as $i => $val)
200  {
201  if ($this->html_images[$i])
202  {
203  $this->atleastoneimage=1;
204  dol_syslog("CMailFile::CMailfile: html_images[$i]['name']=".$this->html_images[$i]['name'], LOG_DEBUG);
205  }
206  }
207  }
208  }
209 
210  // Define if there is at least one file
211  foreach ($filename_list as $i => $val)
212  {
213  if ($filename_list[$i])
214  {
215  $this->atleastonefile=1;
216  dol_syslog("CMailFile::CMailfile: filename_list[$i]=".$filename_list[$i].", mimetype_list[$i]=".$mimetype_list[$i]." mimefilename_list[$i]=".$mimefilename_list[$i], LOG_DEBUG);
217  }
218  }
219 
220  // Add autocopy to (Note: Adding bcc for specific modules are also done from pages)
221  if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_TO)) $addr_bcc.=($addr_bcc?', ':'').$conf->global->MAIN_MAIL_AUTOCOPY_TO;
222 
223  // Action according to choosed sending method
224  if ($this->sendmode == 'mail')
225  {
226  // Use mail php function (default PHP method)
227  // ------------------------------------------
228 
229  $smtp_headers = "";
230  $mime_headers = "";
231  $text_body = "";
232  $files_encoded = "";
233 
234  // Define smtp_headers
235  $this->subject = $subject;
236  $this->addr_from = $from;
237  $this->reply_to = $from; // Set this property after constructor if you want to use another value
238  $this->errors_to = $errors_to;
239  $this->addr_to = $to;
240  $this->addr_cc = $addr_cc;
241  $this->addr_bcc = $addr_bcc;
242  $this->deliveryreceipt = $deliveryreceipt;
243  $this->trackid = $trackid;
244 
245  $smtp_headers = $this->write_smtpheaders();
246  if (! empty($moreinheader)) $smtp_headers.=$moreinheader; // $moreinheader contains the \r\n
247 
248  // Define mime_headers
249  $mime_headers = $this->write_mimeheaders($filename_list, $mimefilename_list);
250 
251  if (! empty($this->html))
252  {
253  if (!empty($css))
254  {
255  $this->css = $css;
256  $this->buildCSS(); // Build a css style (mode = all) into this->styleCSS and this->bodyCSS
257  }
258 
259  $msg = $this->html;
260  }
261 
262  // Define body in text_body
263  $text_body = $this->write_body($msg);
264 
265  // Add attachments to text_encoded
266  if ($this->atleastonefile)
267  {
268  $files_encoded = $this->write_files($filename_list,$mimetype_list,$mimefilename_list);
269  }
270 
271  // We now define $this->headers and $this->message
272  $this->headers = $smtp_headers . $mime_headers;
273  // On nettoie le header pour qu'il ne se termine pas par un retour chariot.
274  // Ceci evite aussi les lignes vides en fin qui peuvent etre interpretees
275  // comme des injections mail par les serveurs de messagerie.
276  $this->headers = preg_replace("/([\r\n]+)$/i","",$this->headers);
277 
278  //$this->message = $this->eol.'This is a message with multiple parts in MIME format.'.$this->eol;
279  $this->message = 'This is a message with multiple parts in MIME format.'.$this->eol;
280  $this->message.= $text_body . $files_encoded;
281  $this->message.= "--" . $this->mixed_boundary . "--" . $this->eol;
282  }
283  else if ($this->sendmode == 'smtps')
284  {
285  // Use SMTPS library
286  // ------------------------------------------
287 
288  require_once DOL_DOCUMENT_ROOT.'/core/class/smtps.class.php';
289  $smtps = new SMTPs();
290  $smtps->setCharSet($conf->file->character_set_client);
291 
292  $smtps->setSubject($this->encodetorfc2822($subject));
293  $smtps->setTO($this->getValidAddress($to,0,1));
294  $smtps->setFrom($this->getValidAddress($from,0,1));
295  $smtps->setTrackId($trackid);
296  $smtps->setReplyTo($this->getValidAddress($from,0,1)); // Set property with this->smtps->setReplyTo after constructor if you want to use another value than the From
297 
298  if (! empty($moreinheader)) $smtps->setMoreInHeader($moreinheader);
299 
300  if (! empty($this->html))
301  {
302  if (!empty($css))
303  {
304  $this->css = $css;
305  $this->buildCSS();
306  }
307  $msg = $this->html;
308  $msg = $this->checkIfHTML($msg);
309  }
310 
311  if ($this->msgishtml) $smtps->setBodyContent($msg,'html');
312  else $smtps->setBodyContent($msg,'plain');
313 
314  if ($this->atleastoneimage)
315  {
316  foreach ($this->images_encoded as $img)
317  {
318  $smtps->setImageInline($img['image_encoded'],$img['name'],$img['content_type'],$img['cid']);
319  }
320  }
321 
322  if ($this->atleastonefile)
323  {
324  foreach ($filename_list as $i => $val)
325  {
326  $content=file_get_contents($filename_list[$i]);
327  $smtps->setAttachment($content,$mimefilename_list[$i],$mimetype_list[$i]);
328  }
329  }
330 
331  $smtps->setCC($addr_cc);
332  $smtps->setBCC($addr_bcc);
333  $smtps->setErrorsTo($errors_to);
334  $smtps->setDeliveryReceipt($deliveryreceipt);
335 
336  $this->smtps=$smtps;
337  }
338  // TODO not stable, in progress
339  else if ($this->sendmode == 'phpmailer')
340  {
341  // Use PHPMailer library
342  // ------------------------------------------
343 
344  require_once DOL_DOCUMENT_ROOT.'/includes/phpmailer/class.phpmailer.php';
345  $this->phpmailer = new PHPMailer();
346  $this->phpmailer->CharSet = $conf->file->character_set_client;
347 
348  $this->phpmailer->Subject($this->encodetorfc2822($subject));
349  $this->phpmailer->setTO($this->getValidAddress($to,0,1));
350  $this->phpmailer->SetFrom($this->getValidAddress($from,0,1));
351  $this->phpmailer->SetReplyTo($this->getValidAddress($from,0,1)); // Set property with this->phpmailer->setReplyTo after constructor if you want to use another value than the From
352  // TODO Add trackid into smtp header
353  // TODO if (! empty($moreinheader)) ...
354 
355  if (! empty($this->html))
356  {
357  if (!empty($css))
358  {
359  $this->css = $css;
360  $this->buildCSS();
361  }
362  $msg = $this->html;
363  $msg = $this->checkIfHTML($msg);
364  }
365 
366  if ($this->msgishtml) $smtps->setBodyContent($msg,'html');
367  else $smtps->setBodyContent($msg,'plain');
368 
369  if ($this->atleastoneimage)
370  {
371  foreach ($this->images_encoded as $img)
372  {
373  $smtps->setImageInline($img['image_encoded'],$img['name'],$img['content_type'],$img['cid']);
374  }
375  }
376 
377  if ($this->atleastonefile)
378  {
379  foreach ($filename_list as $i => $val)
380  {
381  $content=file_get_contents($filename_list[$i]);
382  $smtps->setAttachment($content,$mimefilename_list[$i],$mimetype_list[$i]);
383  }
384  }
385 
386  $this->phpmailer->setCC($addr_cc);
387  $this->phpmailer->setBCC($addr_bcc);
388  $this->phpmailer->setErrorsTo($errors_to);
389  $this->phpmailer->setDeliveryReceipt($deliveryreceipt);
390  }
391  else if ($this->sendmode == 'swiftmailer')
392  {
393  // Use Swift Mailer library
394  // ------------------------------------------
395 
396  $host = dol_getprefix('email');
397 
398  require_once DOL_DOCUMENT_ROOT.'/includes/swiftmailer/lib/swift_required.php';
399  // Create the message
400  $this->message = Swift_Message::newInstance();
401 
402  // Adding a trackid header to a message
403  $headers = $this->message->getHeaders();
404  $headers->addTextHeader('X-Dolibarr-TRACKID', $trackid);
405  $headerID = time() . '.swiftmailer-dolibarr-' . $trackid . '@' . $host;
406  $msgid = $headers->get('Message-ID');
407  $msgid->setId($headerID);
408  $headers->addIdHeader('References', $headerID);
409  // TODO if (! empty($moreinheader)) ...
410 
411  // Give the message a subject
412  $this->message->setSubject($this->encodetorfc2822($subject));
413 
414  // Set the From address with an associative array
415  //$this->message->setFrom(array('john@doe.com' => 'John Doe'));
416  if (! empty($from)) $this->message->setFrom($this->getArrayAddress($from));
417 
418  // Set the To addresses with an associative array
419  if (! empty($to)) $this->message->setTo($this->getArrayAddress($to));
420 
421  if (! empty($from)) $this->message->SetReplyTo($this->getArrayAddress($from));
422 
423  $this->message->setCharSet($conf->file->character_set_client);
424 
425  if (! empty($this->html))
426  {
427  if (!empty($css))
428  {
429  $this->css = $css;
430  $this->buildCSS();
431  }
432  $msg = $this->html;
433  $msg = $this->checkIfHTML($msg);
434  }
435 
436  if ($this->atleastoneimage)
437  {
438  foreach ($this->images_encoded as $img)
439  {
440  //$img['fullpath'],$img['image_encoded'],$img['name'],$img['content_type'],$img['cid']
441  $attachment = Swift_Image::fromPath($img['fullpath'], $img['content_type']);
442  // embed image
443  $imgcid = $this->message->embed($attachment);
444  // replace cid by the one created by swiftmail in html message
445  $msg = str_replace("cid:".$img['cid'], $imgcid, $msg);
446  }
447  }
448 
449  if ($this->msgishtml) {
450  $this->message->setBody($msg,'text/html');
451  // And optionally an alternative body
452  //$this->message->addPart('Here is the message itself', 'text/plain');
453  } else {
454  $this->message->setBody($msg,'text/plain');
455  // And optionally an alternative body
456  //$this->message->addPart('<q>Here is the message itself</q>', 'text/html');
457  }
458 
459  if ($this->atleastonefile)
460  {
461  foreach ($filename_list as $i => $val)
462  {
463  //$this->message->attach(Swift_Attachment::fromPath($filename_list[$i],$mimetype_list[$i]));
464  $attachment = Swift_Attachment::fromPath($filename_list[$i],$mimetype_list[$i]);
465  $this->message->attach($attachment);
466  }
467  }
468 
469  if (! empty($addr_cc)) $this->message->setCc($this->getArrayAddress($addr_cc));
470  if (! empty($addr_bcc)) $this->message->setBcc($this->getArrayAddress($addr_bcc));
471  //if (! empty($errors_to)) $this->message->setErrorsTo($this->getArrayAddress($errors_to);
472  if (isset($this->deliveryreceipt) && $this->deliveryreceipt == 1) $this->message->setReadReceiptTo($this->getArrayAddress($from));
473  }
474  else
475  {
476  // Send mail method not correctly defined
477  // --------------------------------------
478  $this->error = 'Bad value for sendmode';
479  }
480 
481  }
482 
483 
489  function sendfile()
490  {
491  global $conf,$db,$langs;
492 
493  $errorlevel=error_reporting();
494  error_reporting($errorlevel ^ E_WARNING); // Desactive warnings
495 
496  $res=false;
497 
498  if (empty($conf->global->MAIN_DISABLE_ALL_MAILS))
499  {
500  require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
501  $hookmanager = new HookManager($db);
502  $hookmanager->initHooks(array('maildao'));
503  $reshook = $hookmanager->executeHooks('doactions', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
504  if (! empty($reshook))
505  {
506  $this->error = "Error in hook maildao doactions " . $reshook;
507  dol_syslog("CMailFile::sendfile: mail end error=" . $this->error, LOG_ERR);
508 
509  return $reshook;
510  }
511 
512  // Check number of recipient is lower or equal than MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL
513  if (empty($conf->global->MAIL_MAX_NB_OF_RECIPIENTS_TO_IN_SAME_EMAIL)) $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_TO_IN_SAME_EMAIL=10;
514  $tmparray1 = explode(',', $this->addr_to);
515  if (count($tmparray1) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_TO_IN_SAME_EMAIL)
516  {
517  $this->error = 'Too much recipients in to:';
518  dol_syslog("CMailFile::sendfile: mail end error=" . $this->error, LOG_WARNING);
519  return false;
520  }
521  if (empty($conf->global->MAIL_MAX_NB_OF_RECIPIENTS_CC_IN_SAME_EMAIL)) $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_CC_IN_SAME_EMAIL=10;
522  $tmparray2 = explode(',', $this->addr_cc);
523  if (count($tmparray2) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_CC_IN_SAME_EMAIL)
524  {
525  $this->error = 'Too much recipients in cc:';
526  dol_syslog("CMailFile::sendfile: mail end error=" . $this->error, LOG_WARNING);
527  return false;
528  }
529  if (empty($conf->global->MAIL_MAX_NB_OF_RECIPIENTS_BCC_IN_SAME_EMAIL)) $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_BCC_IN_SAME_EMAIL=10;
530  $tmparray3 = explode(',', $this->addr_bcc);
531  if (count($tmparray3) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_BCC_IN_SAME_EMAIL)
532  {
533  $this->error = 'Too much recipients in bcc:';
534  dol_syslog("CMailFile::sendfile: mail end error=" . $this->error, LOG_WARNING);
535  return false;
536  }
537  if (empty($conf->global->MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL)) $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL=10;
538  if ((count($tmparray1)+count($tmparray2)+count($tmparray3)) > $conf->global->MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL)
539  {
540  $this->error = 'Too much recipients in to:, cc:, bcc:';
541  dol_syslog("CMailFile::sendfile: mail end error=" . $this->error, LOG_WARNING);
542  return false;
543  }
544 
545  $keyforsmtpserver='MAIN_MAIL_SMTP_SERVER';
546  $keyforsmtpport ='MAIN_MAIL_SMTP_PORT';
547  $keyforsmtpid ='MAIN_MAIL_SMTPS_ID';
548  $keyforsmtppw ='MAIN_MAIL_SMTPS_PW';
549  $keyfortls ='MAIN_MAIL_EMAIL_TLS';
550  $keyforstarttls ='MAIN_MAIL_EMAIL_STARTTLS';
551  if ($this->sendcontext == 'emailing' && !empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'default')
552  {
553  $keyforsmtpserver='MAIN_MAIL_SMTP_SERVER_EMAILING';
554  $keyforsmtpport ='MAIN_MAIL_SMTP_PORT_EMAILING';
555  $keyforsmtpid ='MAIN_MAIL_SMTPS_ID_EMAILING';
556  $keyforsmtppw ='MAIN_MAIL_SMTPS_PW_EMAILING';
557  $keyfortls ='MAIN_MAIL_EMAIL_TLS_EMAILING';
558  $keyforstarttls ='MAIN_MAIL_EMAIL_STARTTLS_EMAILING';
559  }
560 
561  // Action according to choosed sending method
562  if ($this->sendmode == 'mail')
563  {
564  // Use mail php function (default PHP method)
565  // ------------------------------------------
566  dol_syslog("CMailFile::sendfile addr_to=".$this->addr_to.", subject=".$this->subject, LOG_DEBUG);
567  dol_syslog("CMailFile::sendfile header=\n".$this->headers, LOG_DEBUG);
568  //dol_syslog("CMailFile::sendfile message=\n".$message);
569 
570  // If Windows, sendmail_from must be defined
571  if (isset($_SERVER["WINDIR"]))
572  {
573  if (empty($this->addr_from)) $this->addr_from = 'robot@example.com';
574  @ini_set('sendmail_from',$this->getValidAddress($this->addr_from,2));
575  }
576 
577  // Force parameters
578  if (! empty($conf->global->$keyforsmtpserver)) ini_set('SMTP',$conf->global->$keyforsmtpserver);
579  if (! empty($conf->global->$keyforsmtpport)) ini_set('smtp_port',$conf->global->$keyforsmtpport);
580 
581  $dest=$this->getValidAddress($this->addr_to,2);
582  if (! $dest)
583  {
584  $this->error="Failed to send mail with php mail to HOST=".ini_get('SMTP').", PORT=".ini_get('smtp_port')."<br>Recipient address '$dest' invalid";
585  dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR);
586  }
587  else
588  {
589  $additionnalparam = ''; // By default
590  if (! empty($conf->global->MAIN_MAIL_ALLOW_SENDMAIL_F))
591  {
592  // le "Return-Path" (retour des messages bounced) dans les header ne fonctionne pas avec tous les MTA
593  // Le forcage de la valeur grace à l'option -f de sendmail est donc possible si la constante MAIN_MAIL_ALLOW_SENDMAIL_F est definie.
594  // Having this variable defined may create problems with some sendmail (option -f refused)
595  // Having this variable not defined may create problems with some other sendmail (option -f required)
596  $additionnalparam .= ($additionnalparam?' ':'').(! empty($conf->global->MAIN_MAIL_ERRORS_TO) ? '-f' . $this->getValidAddress($conf->global->MAIN_MAIL_ERRORS_TO,2) : ($this->addr_from != '' ? '-f' . $this->getValidAddress($this->addr_from,2) : '') );
597  }
598  if (! empty($conf->global->MAIN_MAIL_SENDMAIL_FORCE_BA)) // To force usage of -ba option. This option tells sendmail to read From: or Sender: to setup sender
599  {
600  $additionnalparam .= ($additionnalparam?' ':'').'-ba';
601  }
602 
603  if (! empty($conf->global->MAIN_MAIL_SENDMAIL_FORCE_ADDPARAM)) $additionnalparam .= ($additionnalparam?' ':'').'-U '.$additionnalparam; // Use -U to add additionnal params
604 
605  dol_syslog("CMailFile::sendfile: mail start HOST=".ini_get('SMTP').", PORT=".ini_get('smtp_port').", additionnal_parameters=".$additionnalparam, LOG_DEBUG);
606 
607  $this->message=stripslashes($this->message);
608 
609  if (! empty($conf->global->MAIN_MAIL_DEBUG)) $this->dump_mail();
610 
611  if (! empty($additionnalparam)) $res = mail($dest, $this->encodetorfc2822($this->subject), $this->message, $this->headers, $additionnalparam);
612  else $res = mail($dest, $this->encodetorfc2822($this->subject), $this->message, $this->headers);
613 
614  if (! $res)
615  {
616  $this->error="Failed to send mail with php mail";
617  $linuxlike=1;
618  if (preg_match('/^win/i',PHP_OS)) $linuxlike=0;
619  if (preg_match('/^mac/i',PHP_OS)) $linuxlike=0;
620  if (! $linuxlike)
621  {
622  $this->error.=" to HOST=".ini_get('SMTP').", PORT=".ini_get('smtp_port'); // This values are value used only for non linuxlike systems
623  }
624  $this->error.=".<br>";
625  $this->error.=$langs->trans("ErrorPhpMailDelivery");
626  dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR);
627  }
628  else
629  {
630  dol_syslog("CMailFile::sendfile: mail end success", LOG_DEBUG);
631  }
632  }
633 
634  if (isset($_SERVER["WINDIR"]))
635  {
636  @ini_restore('sendmail_from');
637  }
638 
639  // Restore parameters
640  if (! empty($conf->global->$keyforsmtpserver)) ini_restore('SMTP');
641  if (! empty($conf->global->$keyforsmtpport)) ini_restore('smtp_port');
642  }
643  else if ($this->sendmode == 'smtps')
644  {
645 
646  // Use SMTPS library
647  // ------------------------------------------
648  $this->smtps->setTransportType(0); // Only this method is coded in SMTPs library
649 
650  // Clean parameters
651  if (empty($conf->global->$keyforsmtpserver)) $conf->global->$keyforsmtpserver=ini_get('SMTP');
652  if (empty($conf->global->$keyforsmtpport)) $conf->global->$keyforsmtpport=ini_get('smtp_port');
653 
654  // If we use SSL/TLS
655  $server=$conf->global->$keyforsmtpserver;
656  $secure='';
657  if (! empty($conf->global->$keyfortls) && function_exists('openssl_open')) $secure='ssl';
658  if (! empty($conf->global->$keyforstarttls) && function_exists('openssl_open')) $secure='tls';
659  $server=($secure?$secure.'://':'').$server;
660 
661  $port=$conf->global->$keyforsmtpport;
662 
663  $this->smtps->setHost($server);
664  $this->smtps->setPort($port); // 25, 465...;
665 
666  $loginid=''; $loginpass='';
667  if (! empty($conf->global->$keyforsmtpid))
668  {
669  $loginid = $conf->global->$keyforsmtpid;
670  $this->smtps->setID($loginid);
671  }
672  if (! empty($conf->global->$keyforsmtppw))
673  {
674  $loginpass = $conf->global->$keyforsmtppw;
675  $this->smtps->setPW($loginpass);
676  }
677 
678  $res=true;
679  $from=$this->smtps->getFrom('org');
680  if (! $from)
681  {
682  $this->error="Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport."<br>Sender address '$from' invalid";
683  dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR);
684  $res=false;
685  }
686  $dest=$this->smtps->getTo();
687  if (! $dest)
688  {
689  $this->error="Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport."<br>Recipient address '$dest' invalid";
690  dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR);
691  $res=false;
692  }
693 
694  if ($res)
695  {
696  if (! empty($conf->global->MAIN_MAIL_DEBUG)) $this->smtps->setDebug(true);
697 
698  $result=$this->smtps->sendMsg();
699  //print $result;
700 
701  if (! empty($conf->global->MAIN_MAIL_DEBUG)) $this->dump_mail();
702 
703  $result=$this->smtps->getErrors();
704  if (empty($this->error) && empty($result)) $res=true;
705  else
706  {
707  if (empty($this->error)) $this->error=$result;
708  dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR);
709  $res=false;
710  }
711  }
712  }
713  else if ($this->sendmode == 'swiftmailer')
714  {
715  // Use Swift Mailer library
716  // ------------------------------------------
717  require_once DOL_DOCUMENT_ROOT.'/includes/swiftmailer/lib/swift_required.php';
718 
719  // Clean parameters
720  if (empty($conf->global->$keyforsmtpserver)) $conf->global->$keyforsmtpserver=ini_get('SMTP');
721  if (empty($conf->global->$keyforsmtpport)) $conf->global->$keyforsmtpport=ini_get('smtp_port');
722 
723  // If we use SSL/TLS
724  $server=$conf->global->$keyforsmtpserver;
725  $secure='';
726  if (! empty($conf->global->$keyfortls) && function_exists('openssl_open')) $secure='ssl';
727  if (! empty($conf->global->$keyforstarttls) && function_exists('openssl_open')) $secure='tls';
728 
729  $this->transport = Swift_SmtpTransport::newInstance($server, $conf->global->$keyforsmtpport, $secure);
730 
731  if (! empty($conf->global->$keyforsmtpid)) $this->transport->setUsername($conf->global->$keyforsmtpid);
732  if (! empty($conf->global->$keyforsmtppw)) $this->transport->setPassword($conf->global->$keyforsmtppw);
733  //$smtps->_msgReplyTo = 'reply@web.com';
734 
735  // Create the Mailer using your created Transport
736  $this->mailer = Swift_Mailer::newInstance($this->transport);
737 
738  if (! empty($conf->global->MAIN_MAIL_DEBUG)) {
739  // To use the ArrayLogger
740  $this->logger = new Swift_Plugins_Loggers_ArrayLogger();
741  // Or to use the Echo Logger
742  //$this->logger = new Swift_Plugins_Loggers_EchoLogger();
743  $this->mailer->registerPlugin(new Swift_Plugins_LoggerPlugin($this->logger));
744  }
745  // send mail
746  try {
747  $result = $this->mailer->send($this->message);
748  } catch (Exception $e) {
749  $this->error = $e->getMessage();
750  }
751  if (! empty($conf->global->MAIN_MAIL_DEBUG)) $this->dump_mail();
752 
753  $res = true;
754  if (! empty($this->error) && ! $result) {
755  dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR);
756  $res=false;
757  } else {
758  $this->error = sprintf ("Sent %d messages\n", $result);
759  }
760  }
761  else
762  {
763 
764  // Send mail method not correctly defined
765  // --------------------------------------
766 
767  return 'Bad value for sendmode';
768  }
769 
770  }
771  else
772  {
773  $this->error='No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS';
774  dol_syslog("CMailFile::sendfile: ".$this->error, LOG_WARNING);
775  }
776 
777  error_reporting($errorlevel); // Reactive niveau erreur origine
778 
779  return $res;
780  }
781 
788  static function encodetorfc2822($stringtoencode)
789  {
790  global $conf;
791  return '=?'.$conf->file->character_set_client.'?B?'.base64_encode($stringtoencode).'?=';
792  }
793 
800  function _encode_file($sourcefile)
801  {
802  $newsourcefile=dol_osencode($sourcefile);
803 
804  if (is_readable($newsourcefile))
805  {
806  $contents = file_get_contents($newsourcefile); // Need PHP 4.3
807  $encoded = chunk_split(base64_encode($contents), 76, $this->eol); // 76 max is defined into http://tools.ietf.org/html/rfc2047
808  return $encoded;
809  }
810  else
811  {
812  $this->error="Error: Can't read file '".$sourcefile."' into _encode_file";
813  dol_syslog("CMailFile::encode_file: ".$this->error, LOG_ERR);
814  return -1;
815  }
816  }
817 
818 
826  function dump_mail()
827  {
828  global $conf,$dolibarr_main_data_root;
829 
830  if (@is_writeable($dolibarr_main_data_root)) // Avoid fatal error on fopen with open_basedir
831  {
832  $outputfile=$dolibarr_main_data_root."/dolibarr_mail.log";
833  $fp = fopen($outputfile,"w");
834 
835  if ($this->sendmode == 'mail')
836  {
837  fputs($fp, $this->headers);
838  fputs($fp, $this->eol); // This eol is added by the mail function, so we add it in log
839  fputs($fp, $this->message);
840  }
841  elseif ($this->sendmode == 'smtps')
842  {
843  fputs($fp, $this->smtps->log); // this->smtps->log is filled only if MAIN_MAIL_DEBUG was set to on
844  }
845  elseif ($this->sendmode == 'swiftmailer')
846  {
847  fputs($fp, $this->logger->dump()); // this->logger is filled only if MAIN_MAIL_DEBUG was set to on
848  }
849 
850  fclose($fp);
851  if (! empty($conf->global->MAIN_UMASK))
852  @chmod($outputfile, octdec($conf->global->MAIN_UMASK));
853  }
854  }
855 
856 
863  function checkIfHTML($msg)
864  {
865  if (!preg_match('/^[\s\t]*<html/i',$msg))
866  {
867  $out = "<html><head><title></title>";
868  if (!empty($this->styleCSS)) $out.= $this->styleCSS;
869  $out.= "</head><body";
870  if (!empty($this->bodyCSS)) $out.= $this->bodyCSS;
871  $out.= ">";
872  $out.= $msg;
873  $out.= "</body></html>";
874  }
875  else
876  {
877  $out = $msg;
878  }
879 
880  return $out;
881  }
882 
888  function buildCSS()
889  {
890  if (! empty($this->css))
891  {
892  // Style CSS
893  $this->styleCSS = '<style type="text/css">';
894  $this->styleCSS.= 'body {';
895 
896  if ($this->css['bgcolor'])
897  {
898  $this->styleCSS.= ' background-color: '.$this->css['bgcolor'].';';
899  $this->bodyCSS.= ' bgcolor="'.$this->css['bgcolor'].'"';
900  }
901  if ($this->css['bgimage'])
902  {
903  // TODO recuperer cid
904  $this->styleCSS.= ' background-image: url("cid:'.$this->css['bgimage_cid'].'");';
905  }
906  $this->styleCSS.= '}';
907  $this->styleCSS.= '</style>';
908  }
909  }
910 
911 
917  function write_smtpheaders()
918  {
919  global $conf;
920  $out = "";
921 
922  $host = dol_getprefix('email');
923 
924  // Sender
925  //$out.= "Sender: ".getValidAddress($this->addr_from,2)).$this->eol2;
926  $out.= "From: ".$this->getValidAddress($this->addr_from,3,1).$this->eol2;
927  if (! empty($conf->global->MAIN_MAIL_SENDMAIL_FORCE_BA))
928  {
929  $out.= "To: ".$this->getValidAddress($this->addr_to,0,1).$this->eol2;
930  }
931  // Return-Path is important because it is used by SPF. Some MTA does not read Return-Path from header but from command line. See option MAIN_MAIL_ALLOW_SENDMAIL_F for that.
932  $out.= "Return-Path: ".$this->getValidAddress($this->addr_from,0,1).$this->eol2;
933  if (isset($this->reply_to) && $this->reply_to) $out.= "Reply-To: ".$this->getValidAddress($this->reply_to,2).$this->eol2;
934  if (isset($this->errors_to) && $this->errors_to) $out.= "Errors-To: ".$this->getValidAddress($this->errors_to,2).$this->eol2;
935 
936  // Receiver
937  if (isset($this->addr_cc) && $this->addr_cc) $out.= "Cc: ".$this->getValidAddress($this->addr_cc,2).$this->eol2;
938  if (isset($this->addr_bcc) && $this->addr_bcc) $out.= "Bcc: ".$this->getValidAddress($this->addr_bcc,2).$this->eol2; // TODO Question: bcc must not be into header, only into SMTP command "RCPT TO". Does php mail support this ?
939 
940  // Delivery receipt
941  if (isset($this->deliveryreceipt) && $this->deliveryreceipt == 1) $out.= "Disposition-Notification-To: ".$this->getValidAddress($this->addr_from,2).$this->eol2;
942 
943  //$out.= "X-Priority: 3".$this->eol2;
944 
945  $out.= 'Date: ' . date("r") . $this->eol2;
946 
947  $trackid = $this->trackid;
948  if ($trackid)
949  {
950  // References is kept in response and Message-ID is returned into In-Reply-To:
951  $out.= 'Message-ID: <' . time() . '.phpmail-dolibarr-'.$trackid.'@' . $host . ">" . $this->eol2; // Uppercase seems replaced by phpmail
952  $out.= 'References: <' . time() . '.phpmail-dolibarr-'.$trackid.'@' . $host . ">" . $this->eol2;
953  $out.= 'X-Dolibarr-TRACKID: '.$trackid. $this->eol2;
954  }
955  else
956  {
957  $out.= 'Message-ID: <' . time() . '.phpmail@' . $host . ">" . $this->eol2;
958  }
959 
960  if (! empty($_SERVER['REMOTE_ADDR'])) $out.= "X-RemoteAddr: " . $_SERVER['REMOTE_ADDR']. $this->eol2;
961  $out.= "X-Mailer: Dolibarr version " . DOL_VERSION ." (using php mail)".$this->eol2;
962  $out.= "Mime-Version: 1.0".$this->eol2;
963 
964  //$out.= "From: ".$this->getValidAddress($this->addr_from,3,1).$this->eol;
965 
966  $out.= "Content-Type: multipart/mixed;".$this->eol2." boundary=\"".$this->mixed_boundary."\"".$this->eol2;
967  $out.= "Content-Transfer-Encoding: 8bit".$this->eol2; // TODO Seems to be ignored. Header is 7bit once received.
968 
969  dol_syslog("CMailFile::write_smtpheaders smtp_header=\n".$out);
970  return $out;
971  }
972 
973 
981  function write_mimeheaders($filename_list, $mimefilename_list)
982  {
983  $mimedone=0;
984  $out = "";
985 
986  if ($filename_list)
987  {
988  $filename_list_size=count($filename_list);
989  for($i=0;$i < $filename_list_size;$i++)
990  {
991  if ($filename_list[$i])
992  {
993  if ($mimefilename_list[$i]) $filename_list[$i] = $mimefilename_list[$i];
994  $out.= "X-attachments: $filename_list[$i]".$this->eol2;
995  }
996  }
997  }
998 
999  dol_syslog("CMailFile::write_mimeheaders mime_header=\n".$out, LOG_DEBUG);
1000  return $out;
1001  }
1002 
1009  function write_body($msgtext)
1010  {
1011  global $conf;
1012 
1013  $out='';
1014 
1015  $out.= "--" . $this->mixed_boundary . $this->eol;
1016 
1017  if ($this->atleastoneimage)
1018  {
1019  $out.= "Content-Type: multipart/alternative;".$this->eol." boundary=\"".$this->alternative_boundary."\"".$this->eol;
1020  $out.= $this->eol;
1021  $out.= "--" . $this->alternative_boundary . $this->eol;
1022  }
1023 
1024  // Make RFC821 Compliant, replace bare linefeeds
1025  $strContent = preg_replace("/(?<!\r)\n/si", "\r\n", $msgtext); // PCRE modifier /s means new lines are common chars
1026  if (! empty($conf->global->MAIN_FIX_FOR_BUGGED_MTA))
1027  {
1028  $strContent = preg_replace("/\r\n/si", "\n", $strContent); // PCRE modifier /s means new lines are common chars
1029  }
1030 
1031  $strContentAltText = '';
1032  if ($this->msgishtml)
1033  {
1034  $strContentAltText = html_entity_decode(strip_tags($strContent));
1035  $strContentAltText = rtrim(wordwrap($strContentAltText, 75, empty($conf->global->MAIN_FIX_FOR_BUGGED_MTA)?"\r\n":"\n"));
1036 
1037  // Check if html header already in message, if not complete the message
1038  $strContent = $this->checkIfHTML($strContent);
1039  }
1040 
1041  // Make RFC2045 Compliant, split lines
1042  //$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content
1043  // TODO Encode main content into base64 and use the chunk_split, or quoted-printable
1044  $strContent = rtrim(wordwrap($strContent, 75, empty($conf->global->MAIN_FIX_FOR_BUGGED_MTA)?"\r\n":"\n")); // TODO Using this method creates unexpected line break on text/plain content.
1045 
1046  if ($this->msgishtml)
1047  {
1048  if ($this->atleastoneimage)
1049  {
1050  $out.= "Content-Type: text/plain; charset=".$conf->file->character_set_client.$this->eol;
1051  //$out.= "Content-Transfer-Encoding: 7bit".$this->eol;
1052  $out.= $this->eol.($strContentAltText?$strContentAltText:strip_tags($strContent)).$this->eol; // Add plain text message
1053  $out.= "--" . $this->alternative_boundary . $this->eol;
1054  $out.= "Content-Type: multipart/related;".$this->eol." boundary=\"".$this->related_boundary."\"".$this->eol;
1055  $out.= $this->eol;
1056  $out.= "--" . $this->related_boundary . $this->eol;
1057  }
1058 
1059  if (! $this->atleastoneimage && $strContentAltText && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) // Add plain text message part before html part
1060  {
1061  $out.= "Content-Type: multipart/alternative;".$this->eol." boundary=\"".$this->alternative_boundary."\"".$this->eol;
1062  $out.= $this->eol;
1063  $out.= "--" . $this->alternative_boundary . $this->eol;
1064  $out.= "Content-Type: text/plain; charset=".$conf->file->character_set_client.$this->eol;
1065  //$out.= "Content-Transfer-Encoding: 7bit".$this->eol;
1066  $out.= $this->eol.$strContentAltText.$this->eol;
1067  $out.= "--" . $this->alternative_boundary . $this->eol;
1068  }
1069 
1070  $out.= "Content-Type: text/html; charset=".$conf->file->character_set_client.$this->eol;
1071  //$out.= "Content-Transfer-Encoding: 7bit".$this->eol; // TODO Use base64
1072  $out.= $this->eol.$strContent.$this->eol;
1073 
1074  if (! $this->atleastoneimage && $strContentAltText && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) // Add plain text message part after html part
1075  {
1076  $out.= "--" . $this->alternative_boundary . "--". $this->eol;
1077  }
1078  }
1079  else
1080  {
1081  $out.= "Content-Type: text/plain; charset=".$conf->file->character_set_client.$this->eol;
1082  //$out.= "Content-Transfer-Encoding: 7bit".$this->eol;
1083  $out.= $this->eol.$strContent.$this->eol;
1084  }
1085 
1086  $out.= $this->eol;
1087 
1088  // Encode images
1089  if ($this->atleastoneimage)
1090  {
1091  $out .= $this->write_images($this->images_encoded);
1092  // always end related and end alternative after inline images
1093  $out .= "--" . $this->related_boundary . "--" . $this->eol;
1094  $out .= $this->eol . "--" . $this->alternative_boundary . "--" . $this->eol;
1095  $out .= $this->eol;
1096  }
1097 
1098  return $out;
1099  }
1100 
1109  function write_files($filename_list,$mimetype_list,$mimefilename_list)
1110  {
1111  $out = '';
1112 
1113  $filename_list_size=count($filename_list);
1114  for($i=0;$i < $filename_list_size;$i++)
1115  {
1116  if ($filename_list[$i])
1117  {
1118  dol_syslog("CMailFile::write_files: i=$i");
1119  $encoded = $this->_encode_file($filename_list[$i]);
1120  if ($encoded >= 0)
1121  {
1122  if ($mimefilename_list[$i]) $filename_list[$i] = $mimefilename_list[$i];
1123  if (! $mimetype_list[$i]) {
1124  $mimetype_list[$i] = "application/octet-stream";
1125  }
1126 
1127  $out.= "--" . $this->mixed_boundary . $this->eol;
1128  $out.= "Content-Disposition: attachment; filename=\"".$filename_list[$i]."\"".$this->eol;
1129  $out.= "Content-Type: " . $mimetype_list[$i] . "; name=\"".$filename_list[$i]."\"".$this->eol;
1130  $out.= "Content-Transfer-Encoding: base64".$this->eol;
1131  $out.= "Content-Description: File Attachment".$this->eol;
1132  $out.= $this->eol;
1133  $out.= $encoded;
1134  $out.= $this->eol;
1135  //$out.= $this->eol;
1136  }
1137  else
1138  {
1139  return $encoded;
1140  }
1141  }
1142  }
1143 
1144  return $out;
1145  }
1146 
1147 
1154  function write_images($images_list)
1155  {
1156  $out = '';
1157 
1158  if ($images_list)
1159  {
1160  foreach ($images_list as $img)
1161  {
1162  dol_syslog("CMailFile::write_images: i=$i");
1163 
1164  $out.= "--" . $this->related_boundary . $this->eol; // always related for an inline image
1165  $out.= "Content-Type: " . $img["content_type"] . "; name=\"".$img["name"]."\"".$this->eol;
1166  $out.= "Content-Transfer-Encoding: base64".$this->eol;
1167  $out.= "Content-Disposition: inline; filename=\"".$img["name"]."\"".$this->eol;
1168  $out.= "Content-ID: <".$img["cid"].">".$this->eol;
1169  $out.= $this->eol;
1170  $out.= $img["image_encoded"];
1171  $out.= $this->eol;
1172  }
1173  }
1174 
1175  return $out;
1176  }
1177 
1178 
1186  function check_server_port($host,$port)
1187  {
1188  global $conf;
1189 
1190  $_retVal=0;
1191  $timeout=5; // Timeout in seconds
1192 
1193  if (function_exists('fsockopen'))
1194  {
1195  $keyforsmtpserver='MAIN_MAIL_SMTP_SERVER';
1196  $keyforsmtpport ='MAIN_MAIL_SMTP_PORT';
1197  $keyforsmtpid ='MAIN_MAIL_SMTPS_ID';
1198  $keyforsmtppw ='MAIN_MAIL_SMTPS_PW';
1199  $keyfortls ='MAIN_MAIL_EMAIL_TLS';
1200  $keyforstarttls ='MAIN_MAIL_EMAIL_STARTTLS';
1201  if ($this->sendcontext == 'emailing' && !empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'default')
1202  {
1203  $keyforsmtpserver='MAIN_MAIL_SMTP_SERVER_EMAILING';
1204  $keyforsmtpport ='MAIN_MAIL_SMTP_PORT_EMAILING';
1205  $keyforsmtpid ='MAIN_MAIL_SMTPS_ID_EMAILING';
1206  $keyforsmtppw ='MAIN_MAIL_SMTPS_PW_EMAILING';
1207  $keyfortls ='MAIN_MAIL_EMAIL_TLS_EMAILING';
1208  $keyforstarttls ='MAIN_MAIL_EMAIL_STARTTLS_EMAILING';
1209  }
1210 
1211  // If we use SSL/TLS
1212  if (! empty($conf->global->$keyfortls) && function_exists('openssl_open')) $host='ssl://'.$host;
1213  // tls smtp start with no encryption
1214  //if (! empty($conf->global->MAIN_MAIL_EMAIL_STARTTLS) && function_exists('openssl_open')) $host='tls://'.$host;
1215 
1216  dol_syslog("Try socket connection to host=".$host." port=".$port);
1217  //See if we can connect to the SMTP server
1218  if ($socket = @fsockopen(
1219  $host, // Host to test, IP or domain. Add ssl:// for SSL/TLS.
1220  $port, // which Port number to use
1221  $errno, // actual system level error
1222  $errstr, // and any text that goes with the error
1223  $timeout
1224  )) // timeout for reading/writing data over the socket
1225  {
1226  // Windows still does not have support for this timeout function
1227  if (function_exists('stream_set_timeout')) stream_set_timeout($socket, $timeout, 0);
1228 
1229  dol_syslog("Now we wait for answer 220");
1230 
1231  // Check response from Server
1232  if ( $_retVal = $this->server_parse($socket, "220") ) $_retVal = $socket;
1233  }
1234  else
1235  {
1236  $this->error = utf8_check('Error '.$errno.' - '.$errstr)?'Error '.$errno.' - '.$errstr:utf8_encode('Error '.$errno.' - '.$errstr);
1237  }
1238  }
1239  return $_retVal;
1240  }
1241 
1250  function server_parse($socket, $response)
1251  {
1252  $_retVal = true; // Indicates if Object was created or not
1253  $server_response = '';
1254 
1255  while (substr($server_response,3,1) != ' ')
1256  {
1257  if (! ($server_response = fgets($socket, 256)) )
1258  {
1259  $this->error="Couldn't get mail server response codes";
1260  return false;
1261  }
1262  }
1263 
1264  if( !( substr($server_response, 0, 3) == $response ) )
1265  {
1266  $this->error="Ran into problems sending Mail.\r\nResponse: $server_response";
1267  $_retVal = false;
1268  }
1269 
1270  return $_retVal;
1271  }
1272 
1279  function findHtmlImages($images_dir)
1280  {
1281  // Build the list of image extensions
1282  $extensions = array_keys($this->image_types);
1283 
1284 
1285  preg_match_all('/(?:"|\')([^"\']+\.('.implode('|', $extensions).'))(?:"|\')/Ui', $this->html, $matches); // If "xxx.ext" or 'xxx.ext' found
1286 
1287  if ($matches)
1288  {
1289  $i=0;
1290  foreach ($matches[1] as $full)
1291  {
1292 
1293  if (preg_match('/file=([A-Za-z0-9_\-\/]+[\.]?[A-Za-z0-9]+)?$/i',$full,$regs)) // If xxx is 'file=aaa'
1294  {
1295  $img = $regs[1];
1296 
1297  if (file_exists($images_dir.'/'.$img))
1298  {
1299  // Image path in src
1300  $src = preg_quote($full,'/');
1301 
1302  // Image full path
1303  $this->html_images[$i]["fullpath"] = $images_dir.'/'.$img;
1304 
1305  // Image name
1306  $this->html_images[$i]["name"] = $img;
1307 
1308  // Content type
1309  if (preg_match('/^.+\.(\w{3,4})$/', $img, $reg))
1310  {
1311  $ext=strtolower($reg[1]);
1312  $this->html_images[$i]["content_type"] = $this->image_types[$ext];
1313  }
1314 
1315  // cid
1316  $this->html_images[$i]["cid"] = dol_hash(uniqid(time()), 3); // Force md5 hash (does not contains special chars)
1317  $this->html = preg_replace("/src=\"$src\"|src='$src'/i", "src=\"cid:".$this->html_images[$i]["cid"]."\"", $this->html);
1318  }
1319  $i++;
1320  }
1321  }
1322 
1323  if (!empty($this->html_images))
1324  {
1325  $inline = array();
1326 
1327  $i=0;
1328 
1329  foreach ($this->html_images as $img)
1330  {
1331  $fullpath = $images_dir.'/'.$img["name"];
1332 
1333  // If duplicate images are embedded, they may show up as attachments, so remove them.
1334  if (!in_array($fullpath,$inline))
1335  {
1336  // Read image file
1337  if ($image = file_get_contents($fullpath))
1338  {
1339  // On garde que le nom de l'image
1340  preg_match('/([A-Za-z0-9_-]+[\.]?[A-Za-z0-9]+)?$/i',$img["name"],$regs);
1341  $imgName = $regs[1];
1342 
1343  $this->images_encoded[$i]['name'] = $imgName;
1344  $this->images_encoded[$i]['fullpath'] = $fullpath;
1345  $this->images_encoded[$i]['content_type'] = $img["content_type"];
1346  $this->images_encoded[$i]['cid'] = $img["cid"];
1347  // Encodage de l'image
1348  $this->images_encoded[$i]["image_encoded"] = chunk_split(base64_encode($image), 68, $this->eol);
1349  $inline[] = $fullpath;
1350  }
1351  }
1352  $i++;
1353  }
1354  }
1355  else
1356  {
1357  return -1;
1358  }
1359 
1360  return 1;
1361  }
1362  else
1363  {
1364  return 0;
1365  }
1366  }
1367 
1381  static function getValidAddress($address,$format,$encode=0,$maxnumberofemail=0)
1382  {
1383  global $conf;
1384 
1385  $ret='';
1386 
1387  $arrayaddress=explode(',',$address);
1388 
1389  // Boucle sur chaque composant de l'adresse
1390  $i=0;
1391  foreach($arrayaddress as $val)
1392  {
1393  if (preg_match('/^(.*)<(.*)>$/i',trim($val),$regs))
1394  {
1395  $name = trim($regs[1]);
1396  $email = trim($regs[2]);
1397  }
1398  else
1399  {
1400  $name = '';
1401  $email = trim($val);
1402  }
1403 
1404  if ($email)
1405  {
1406  $i++;
1407 
1408  $newemail='';
1409  if ($format == 4)
1410  {
1411  $newemail = $name?$name:$email;
1412  }
1413  if ($format == 2)
1414  {
1415  $newemail=$email;
1416  }
1417  if ($format == 1 || $format == 3)
1418  {
1419  $newemail='<'.$email.'>';
1420  }
1421  if ($format == 0 || $format == 3)
1422  {
1423  if (! empty($conf->global->MAIN_MAIL_NO_FULL_EMAIL)) $newemail='<'.$email.'>';
1424  elseif (! $name) $newemail='<'.$email.'>';
1425  else $newemail=($format==3?'"':'').($encode?self::encodetorfc2822($name):$name).($format==3?'"':'').' <'.$email.'>';
1426  }
1427 
1428  $ret=($ret ? $ret.',' : '').$newemail;
1429 
1430  // Stop if we have too much records
1431  if ($maxnumberofemail && $i >= $maxnumberofemail)
1432  {
1433  if (count($arrayaddress) > $maxnumberofemail) $ret.='...';
1434  break;
1435  }
1436  }
1437  }
1438 
1439  return $ret;
1440  }
1441 
1448  function getArrayAddress($address)
1449  {
1450  global $conf;
1451 
1452  $ret=array();
1453 
1454  $arrayaddress=explode(',',$address);
1455 
1456  // Boucle sur chaque composant de l'adresse
1457  foreach($arrayaddress as $val)
1458  {
1459  if (preg_match('/^(.*)<(.*)>$/i',trim($val),$regs))
1460  {
1461  $name = trim($regs[1]);
1462  $email = trim($regs[2]);
1463  }
1464  else
1465  {
1466  $name = null;
1467  $email = trim($val);
1468  }
1469 
1470  $ret[$email]=empty($conf->global->MAIN_MAIL_NO_FULL_EMAIL)?$name:null;
1471  }
1472 
1473  return $ret;
1474  }
1475 }
1476 
checkIfHTML($msg)
Correct an uncomplete html string.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
write_body($msgtext)
Return email content (mode = 'mail')
findHtmlImages($images_dir)
Seearch images into html message and init array this->images_encoded if found.
__construct($subject, $to, $from, $msg, $filename_list=array(), $mimetype_list=array(), $mimefilename_list=array(), $addr_cc="", $addr_bcc="", $deliveryreceipt=0, $msgishtml=0, $errors_to='', $css='', $trackid='', $moreinheader='', $sendcontext='standard')
CMailFile.
getArrayAddress($address)
Return a formatted array of address string for SMTP protocol.
Class to construct and send SMTP compliant email, even to a secure SMTP server, regardless of platfor...
Definition: smtps.class.php:46
write_images($images_list)
Attach an image to email (mode = 'mail')
if(GETPOST('cancel','alpha')) if(!GETPOST('confirmmassaction','alpha')&&$massaction!= 'presend'&&$massaction!= 'confirm_presend')
Draft customers invoices.
Definition: list.php:147
write_mimeheaders($filename_list, $mimefilename_list)
Create header MIME (mode = 'mail')
write_files($filename_list, $mimetype_list, $mimefilename_list)
Attach file to email (mode = 'mail')
$bodyCSS
Defined background directly in body tag.
Class to manage hooks.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
server_parse($socket, $response)
This function has been modified as provided by SirSir to allow multiline responses when using SMTP Ex...
static getValidAddress($address, $format, $encode=0, $maxnumberofemail=0)
Return a formatted address string for SMTP protocol.
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,$sendto,$replyto,$message,$filepath,$mimetype,$filename,$cc,$ccc,$deliveryreceipt,$msgishtml,$errors_to,$css,$trackid,$moreinheader,$sendcontext); $mailfile->sendfile();.
$styleCSS
Defined css style for body background.
utf8_check($str)
Check if a string is in UTF8.
dump_mail()
Write content of a SMTP request into a dump file (mode = all) Used for debugging. ...
check_server_port($host, $port)
Try to create a socket connection.
static encodetorfc2822($stringtoencode)
Encode subject according to RFC 2822 - http://en.wikipedia.org/wiki/MIME#Encoded-Word.
sendfile()
Send mail that was prepared by constructor.
_encode_file($sourcefile)
Read a file on disk and return encoded content for emails (mode = 'mail')
dol_hash($chain, $type='0')
Returns a hash of a string.
write_smtpheaders()
Create SMTP headers (mode = 'mail')
buildCSS()
Build a css style (mode = all) into this->styleCSS and this->bodyCSS.
dol_textishtml($msg, $option=0)
Return if a text is a html content.