2002-04-30 12:44:42 +02:00
< ? php
2011-12-28 12:48:18 +01:00
/**
2019-03-06 20:29:58 +01:00
* Copyright ( C ) Dan Potter
* Copyright ( C ) Eric Seigne
* Copyright ( C ) 2000 - 2005 Rodolphe Quiedeville < rodolphe @ quiedeville . org >
* Copyright ( C ) 2003 Jean - Louis Bergamo < jlb @ j1b . org >
* Copyright ( C ) 2004 - 2015 Laurent Destailleur < eldy @ users . sourceforge . net >
* Copyright ( C ) 2005 - 2012 Regis Houssin < regis . houssin @ inodbox . com >
2022-08-02 11:01:09 +02:00
* Copyright ( C ) 2019 - 2022 Frédéric France < frederic . france @ netlogic . fr >
2005-06-25 15:02:39 +02:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2013-01-16 15:36:08 +01:00
* the Free Software Foundation ; either version 3 of the License , or
2005-06-25 15:02:39 +02:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2019-09-23 21:55:30 +02:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
* or see https :// www . gnu . org /
2005-06-25 15:02:39 +02:00
*
* Lots of code inspired from Dan Potter ' s CMailFile class
*/
/**
2011-10-24 09:29:17 +02:00
* \file htdocs / core / class / CMailFile . class . php
2010-08-28 12:55:11 +02:00
* \brief File of class to send emails ( with attachments or not )
2008-11-15 01:52:42 +01:00
*/
2004-07-16 00:17:39 +02:00
2022-08-01 11:31:32 +02:00
use OAuth\Common\Storage\DoliStorage ;
2022-08-11 10:03:44 +02:00
use OAuth\Common\Consumer\Credentials ;
2023-03-13 10:30:37 +01:00
2005-06-25 15:02:39 +02:00
/**
2012-02-01 16:00:22 +01:00
* Class to send emails ( with attachments or not )
2020-08-31 17:00:43 +02:00
* Usage : $mailfile = new CMailFile ( $subject , $sendto , $replyto , $message , $filepath , $mimetype , $filename , $cc , $ccc , $deliveryreceipt , $msgishtml , $errors_to , $css , $trackid , $moreinheader , $sendcontext , $replyto );
2012-02-01 16:00:22 +01:00
* $mailfile -> sendfile ();
2008-11-15 01:52:42 +01:00
*/
2004-07-16 00:17:39 +02:00
class CMailFile
2003-07-07 12:04:20 +02:00
{
2017-04-18 01:39:06 +02:00
public $sendcontext ;
public $sendmode ;
public $sendsetup ;
2017-08-24 02:02:00 +02:00
2021-01-16 14:12:09 +01:00
/**
* @ var string Subject of email
*/
public $subject ;
2020-09-07 10:18:17 +02:00
public $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).
2017-04-18 01:39:06 +02:00
// Sender: Who send the email ("Sender" has sent emails on behalf of "From").
// 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.
// Return-Path: Email where to send bounds.
2020-09-07 10:18:17 +02:00
public $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)
public $errors_to ; // Errors-To: Email where to send errors.
public $addr_to ;
public $addr_cc ;
public $addr_bcc ;
public $trackid ;
2008-11-15 01:52:42 +01:00
2020-09-07 10:18:17 +02:00
public $mixed_boundary ;
public $related_boundary ;
public $alternative_boundary ;
public $deliveryreceipt ;
2008-11-15 01:52:42 +01:00
2020-12-01 11:35:30 +01:00
public $atleastonefile ;
2023-02-16 21:48:55 +01:00
public $msg ;
2020-09-07 10:18:17 +02:00
public $eol ;
public $eol2 ;
2018-09-20 17:46:39 +02:00
/**
* @ var string Error code ( or message )
*/
2019-11-13 18:32:11 +01:00
public $error = '' ;
2008-11-15 01:52:42 +01:00
2022-08-10 13:38:18 +02:00
/**
* @ var string [] Array of Error code ( or message )
*/
public $errors = array ();
2020-09-07 10:18:17 +02:00
public $smtps ; // Contains SMTPs object (if this method is used)
public $phpmailer ; // Contains PHPMailer object (if this method is used)
2009-05-18 00:54:12 +02:00
2022-08-10 10:59:57 +02:00
/**
* @ var Swift_SmtpTransport
*/
public $transport ;
/**
* @ var Swift_Mailer
*/
public $mailer ;
2022-08-10 13:38:18 +02:00
/**
* @ var Swift_Plugins_Loggers_ArrayLogger
*/
public $logger ;
2018-11-19 23:38:07 +01:00
/**
* @ var string CSS
*/
public $css ;
2009-11-18 16:40:17 +01:00
//! Defined css style for body background
2020-09-07 10:18:17 +02:00
public $styleCSS ;
2013-03-15 18:27:48 +01:00
//! Defined background directly in body tag
2020-09-07 10:18:17 +02:00
public $bodyCSS ;
2009-05-24 22:01:25 +02:00
2020-09-07 10:18:17 +02:00
public $msgid ;
public $headers ;
public $message ;
/**
2020-02-06 12:58:02 +01:00
* @ var array fullfilenames list ( full path of filename on file system )
2019-09-17 10:15:55 +02:00
*/
public $filename_list = array ();
/**
2020-02-06 12:58:02 +01:00
* @ var array mimetypes of files list ( List of MIME type of attached files )
2019-09-17 10:15:55 +02:00
*/
public $mimetype_list = array ();
/**
2020-02-06 12:58:02 +01:00
* @ var array filenames list ( List of attached file name in message )
2019-09-17 10:15:55 +02:00
*/
public $mimefilename_list = array ();
2022-10-23 17:14:23 +02:00
/**
* @ var array filenames cid
*/
public $cid_list = array ();
2015-05-05 04:10:42 +02:00
2009-05-17 16:22:57 +02:00
// Image
2020-09-07 10:18:17 +02:00
public $html ;
2023-02-22 21:38:26 +01:00
public $msgishtml ;
2020-09-07 10:18:17 +02:00
public $image_boundary ;
public $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).
public $html_images = array ();
public $images_encoded = array ();
public $image_types = array (
'gif' => 'image/gif' ,
2018-01-21 15:55:56 +01:00
'jpg' => 'image/jpeg' ,
'jpeg' => 'image/jpeg' ,
'jpe' => 'image/jpeg' ,
'bmp' => 'image/bmp' ,
'png' => 'image/png' ,
'tif' => 'image/tiff' ,
2020-09-07 10:18:17 +02:00
'tiff' => 'image/tiff' ,
);
2009-02-09 01:04:34 +01:00
2008-11-15 01:52:42 +01:00
/**
2011-07-04 11:36:29 +02:00
* CMailFile
2011-07-20 13:07:12 +02:00
*
2011-12-07 17:28:11 +01:00
* @ param string $subject Topic / Subject of mail
2015-03-19 11:47:30 +01:00
* @ param string $to Recipients emails ( RFC 2822 : " Name firstname <email>[, ...] " or " email[, ...] " or " <email>[, ...] " ) . Note : the keyword '__SUPERVISOREMAIL__' is not allowed here and must be replaced by caller .
* @ param string $from Sender email ( RFC 2822 : " Name firstname <email>[, ...] " or " email[, ...] " or " <email>[, ...] " )
2011-12-07 17:28:11 +01:00
* @ param string $msg Message
* @ param array $filename_list List of files to attach ( full path of filename on file system )
* @ param array $mimetype_list List of MIME type of attached files
* @ param array $mimefilename_list List of attached file name in message
2021-11-19 22:28:35 +01:00
* @ param string $addr_cc Email cc ( Example : 'abc@def.com, ghk@lmn.com' )
2014-04-25 16:45:14 +02:00
* @ param string $addr_bcc Email bcc ( Note : This is autocompleted with MAIN_MAIL_AUTOCOPY_TO if defined )
* @ param int $deliveryreceipt Ask a delivery receipt
* @ param int $msgishtml 1 = String IS already html , 0 = String IS NOT html , - 1 = Unknown make autodetection ( with fast mode , not reliable )
2015-05-05 04:10:42 +02:00
* @ param string $errors_to Email for errors - to
2014-04-25 16:45:14 +02:00
* @ param string $css Css option
2017-04-11 10:57:17 +02:00
* @ param string $trackid Tracking string ( contains type and id of related element )
2022-08-31 14:02:09 +02:00
* @ param string $moreinheader More in header . $moreinheader must contains the " \r \n " ( TODO not supported for other MAIL_SEND_MODE different than 'mail' and 'smtps' for the moment )
2019-09-30 15:18:05 +02:00
* @ param string $sendcontext 'standard' , 'emailing' , ... ( used to define which sending mode and parameters to use )
2018-02-28 19:09:05 +01:00
* @ param string $replyto Reply - to email ( will be set to same value than From by default if not provided )
2022-10-23 17:14:23 +02:00
* @ param string $upload_dir_tmp Temporary directory ( used to convert images embedded as img src = data : image )
2008-11-15 01:52:42 +01:00
*/
2022-10-23 17:14:23 +02:00
public 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' , $replyto = '' , $upload_dir_tmp = '' )
2008-11-15 01:52:42 +01:00
{
2022-03-17 12:39:39 +01:00
global $conf , $dolibarr_main_data_root , $user ;
2009-05-16 20:11:38 +02:00
2023-02-16 21:46:27 +01:00
dol_syslog ( " CMailFile::CMailfile: charset= " . $conf -> file -> character_set_client . " from= $from , to= $to , addr_cc= $addr_cc , addr_bcc= $addr_bcc , errors_to= $errors_to , replyto= $replyto trackid= $trackid sendcontext= $sendcontext " , LOG_DEBUG );
2023-02-16 21:44:38 +01:00
dol_syslog ( " CMailFile::CMailfile: subject= " . $subject . " , deliveryreceipt= " . $deliveryreceipt . " , msgishtml= " . $msgishtml , LOG_DEBUG );
2023-03-13 10:30:37 +01:00
2020-02-06 12:58:02 +01:00
// Clean values of $mimefilename_list
if ( is_array ( $mimefilename_list )) {
2020-04-10 10:59:32 +02:00
foreach ( $mimefilename_list as $key => $val ) {
2020-02-06 12:58:02 +01:00
$mimefilename_list [ $key ] = dol_string_unaccent ( $mimefilename_list [ $key ]);
}
}
2022-10-23 17:14:23 +02:00
$cid_list = array ();
2017-04-18 01:39:06 +02:00
$this -> sendcontext = $sendcontext ;
2017-08-24 02:02:00 +02:00
2022-08-31 14:02:09 +02:00
// Define this->sendmode ('mail', 'smtps', 'siwftmailer', ...) according to $sendcontext ('standard', 'emailing', 'ticket')
2017-04-18 01:39:06 +02:00
$this -> sendmode = '' ;
2020-09-02 15:33:18 +02:00
if ( ! empty ( $this -> sendcontext )) {
$smtpContextKey = strtoupper ( $this -> sendcontext );
2022-08-31 14:02:09 +02:00
$smtpContextSendMode = getDolGlobalString ( 'MAIN_MAIL_SENDMODE_' . $smtpContextKey );
2020-09-02 15:33:18 +02:00
if ( ! empty ( $smtpContextSendMode ) && $smtpContextSendMode != 'default' ) {
$this -> sendmode = $smtpContextSendMode ;
}
2017-08-24 02:02:00 +02:00
}
2021-01-16 14:12:09 +01:00
if ( empty ( $this -> sendmode )) {
2022-02-28 14:10:35 +01:00
$this -> sendmode = ( ! empty ( $conf -> global -> MAIN_MAIL_SENDMODE ) ? $conf -> global -> MAIN_MAIL_SENDMODE : 'mail' );
2021-01-16 14:12:09 +01:00
}
2017-04-18 01:39:06 +02:00
2012-11-13 17:25:47 +01:00
// We define end of line (RFC 821).
2019-11-13 18:32:11 +01:00
$this -> eol = " \r \n " ;
2013-03-13 19:14:49 +01:00
// We define end of line for header fields (RFC 822bis section 2.3 says header must contains \r\n).
2019-11-13 18:32:11 +01:00
$this -> eol2 = " \r \n " ;
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_FIX_FOR_BUGGED_MTA )) {
2019-11-13 18:32:11 +01:00
$this -> eol = " \n " ;
$this -> eol2 = " \n " ;
2019-01-27 11:55:16 +01:00
$moreinheader = str_replace ( " \r \n " , " \n " , $moreinheader );
2012-11-13 17:25:47 +01:00
}
2009-05-18 00:54:12 +02:00
2011-03-25 19:12:58 +01:00
// On defini mixed_boundary
2019-11-13 18:32:11 +01:00
$this -> mixed_boundary = " multipart_x. " . time () . " .x_boundary " ;
2009-05-17 12:27:13 +02:00
// On defini related_boundary
2019-11-13 18:32:11 +01:00
$this -> related_boundary = 'mul_' . dol_hash ( uniqid ( " dolibarr2 " ), 3 ); // Force md5 hash (does not contains special chars)
2009-05-17 12:27:13 +02:00
// On defini alternative_boundary
2019-11-13 18:32:11 +01:00
$this -> alternative_boundary = 'mul_' . dol_hash ( uniqid ( " dolibarr3 " ), 3 ); // Force md5 hash (does not contains special chars)
2009-05-13 21:10:06 +02:00
2021-01-16 14:12:09 +01:00
if ( empty ( $subject )) {
2017-04-18 01:39:06 +02:00
dol_syslog ( " CMailFile::CMailfile: Try to send an email with empty subject " );
2019-11-13 18:32:11 +01:00
$this -> error = 'ErrorSubjectIsRequired' ;
2017-04-18 01:39:06 +02:00
return ;
2016-06-24 15:36:20 +02:00
}
2021-01-16 14:12:09 +01:00
if ( empty ( $msg )) {
2020-09-07 10:18:17 +02:00
dol_syslog ( " CMailFile::CMailfile: Try to send an email with empty body " );
$msg = '.' ; // Avoid empty message (with empty message content, you will see a multipart structure)
2017-08-24 02:02:00 +02:00
}
2016-06-24 15:36:20 +02:00
2008-07-17 01:37:34 +02:00
// Detect if message is HTML (use fast method)
2021-01-16 14:12:09 +01:00
if ( $msgishtml == - 1 ) {
2007-10-04 21:59:21 +02:00
$this -> msgishtml = 0 ;
2021-01-16 14:12:09 +01:00
if ( dol_textishtml ( $msg )) {
$this -> msgishtml = 1 ;
}
2020-05-21 15:05:19 +02:00
} else {
2007-10-04 21:59:21 +02:00
$this -> msgishtml = $msgishtml ;
}
2006-08-06 20:34:37 +02:00
2017-08-28 00:06:19 +02:00
global $dolibarr_main_url_root ;
// Define $urlwithroot
2019-11-13 18:32:11 +01:00
$urlwithouturlroot = preg_replace ( '/' . preg_quote ( DOL_URL_ROOT , '/' ) . '$/i' , '' , trim ( $dolibarr_main_url_root ));
$urlwithroot = $urlwithouturlroot . DOL_URL_ROOT ; // This is to use external domain name found into config file
2017-08-28 00:06:19 +02:00
//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
// Replace relative /viewimage to absolute path
2020-02-09 15:51:43 +01:00
$msg = preg_replace ( '/src="' . preg_quote ( DOL_URL_ROOT , '/' ) . '\/viewimage\.php/ims' , 'src="' . $urlwithroot . '/viewimage.php' , $msg , - 1 );
2017-08-28 00:06:19 +02:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_FORCE_CONTENT_TYPE_TO_HTML )) {
$this -> msgishtml = 1 ; // To force to send everything with content type html.
}
2017-01-11 16:47:17 +01:00
2009-05-11 19:13:56 +02:00
// Detect images
2021-01-16 14:12:09 +01:00
if ( $this -> msgishtml ) {
2009-05-11 19:13:56 +02:00
$this -> html = $msg ;
2011-11-16 23:58:25 +01:00
2020-12-07 15:36:37 +01:00
$findimg = 0 ;
2023-02-25 04:05:18 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_ADD_INLINE_IMAGES_IF_IN_MEDIAS )) { // Off by default
2022-10-23 17:14:23 +02:00
// Search into the body for <img tags of links in medias files to replace them with an embedded file
// Note because media links are public, this should be useless, except avoid blocking images with email browser.
// This convert an embedd file with src="/viewimage.php?modulepart... into a cid link
2023-02-25 04:05:18 +01:00
// TODO Exclude viewimage used for the read tracker ?
2017-04-18 01:39:06 +02:00
$findimg = $this -> findHtmlImages ( $dolibarr_main_data_root . '/medias' );
}
2023-02-25 04:05:18 +01:00
2022-10-23 17:14:23 +02:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_ADD_INLINE_IMAGES_IF_DATA )) {
// Search into the body for <img src="data:image/ext;base64,..." to replace them with an embedded file
// This convert an embedded file with src="data:image... into a cid link + attached file
$findimg = $this -> findHtmlImagesIsSrcData ( $upload_dir_tmp );
}
2017-04-18 01:39:06 +02:00
2022-10-23 17:14:23 +02:00
// Set atleastoneimage if there is at least one embedded file (into ->html_images)
2022-11-21 18:30:17 +01:00
if ( $findimg > 0 ) {
2021-01-16 14:12:09 +01:00
foreach ( $this -> html_images as $i => $val ) {
if ( $this -> html_images [ $i ]) {
2019-11-13 18:32:11 +01:00
$this -> atleastoneimage = 1 ;
2022-10-23 17:14:23 +02:00
if ( $this -> html_images [ $i ][ 'type' ] == 'cidfromdata' ) {
2023-02-23 18:29:58 +01:00
if ( ! in_array ( $this -> html_images [ $i ][ 'fullpath' ], $filename_list )) {
// If this file path is not already into the $filename_list, we add it.
$posindice = count ( $filename_list );
$filename_list [ $posindice ] = $this -> html_images [ $i ][ 'fullpath' ];
$mimetype_list [ $posindice ] = $this -> html_images [ $i ][ 'content_type' ];
$mimefilename_list [ $posindice ] = $this -> html_images [ $i ][ 'name' ];
} else {
$posindice = array_search ( $this -> html_images [ $i ][ 'fullpath' ], $filename_list );
}
// We complete the array of cid_list
2022-10-23 17:14:23 +02:00
$cid_list [ $posindice ] = $this -> html_images [ $i ][ 'cid' ];
}
2009-05-11 19:13:56 +02:00
dol_syslog ( " CMailFile::CMailfile: html_images[ $i ]['name']= " . $this -> html_images [ $i ][ 'name' ], LOG_DEBUG );
}
}
}
}
2023-02-23 18:29:58 +01:00
//var_dump($filename_list);
//var_dump($cid_list);exit;
2009-05-11 19:13:56 +02:00
2022-10-23 17:14:23 +02:00
// Set atleastoneimage if there is at least one file (into $filename_list array)
2021-01-16 14:12:09 +01:00
if ( is_array ( $filename_list )) {
foreach ( $filename_list as $i => $val ) {
if ( $filename_list [ $i ]) {
2019-11-13 18:32:11 +01:00
$this -> atleastonefile = 1 ;
2022-10-23 17:14:23 +02:00
dol_syslog ( " CMailFile::CMailfile: filename_list[ $i ]= " . $filename_list [ $i ] . " , mimetype_list[ $i ]= " . $mimetype_list [ $i ] . " mimefilename_list[ $i ]= " . $mimefilename_list [ $i ] . " cid_list[ $i ]= " . $cid_list [ $i ], LOG_DEBUG );
2018-06-01 17:20:49 +02:00
}
2009-02-09 01:04:34 +01:00
}
2006-08-06 20:34:37 +02:00
}
2004-07-16 08:41:58 +02:00
2022-03-17 12:39:39 +01:00
// Add auto copy to if not already in $to (Note: Adding bcc for specific modules are also done from pages)
// For example MAIN_MAIL_AUTOCOPY_TO can be 'email@example.com, __USER_EMAIL__, ...'
if ( ! empty ( $conf -> global -> MAIN_MAIL_AUTOCOPY_TO )) {
$listofemailstoadd = explode ( ',' , $conf -> global -> MAIN_MAIL_AUTOCOPY_TO );
foreach ( $listofemailstoadd as $key => $val ) {
$emailtoadd = $listofemailstoadd [ $key ];
if ( trim ( $emailtoadd ) == '__USER_EMAIL__' ) {
if ( ! empty ( $user ) && ! empty ( $user -> email )) {
$emailtoadd = $user -> email ;
} else {
$emailtoadd = '' ;
}
}
if ( $emailtoadd && preg_match ( '/' . preg_quote ( $emailtoadd , '/' ) . '/i' , $to )) {
$emailtoadd = '' ; // Email already in the "To"
}
if ( $emailtoadd ) {
$listofemailstoadd [ $key ] = $emailtoadd ;
} else {
unset ( $listofemailstoadd [ $key ]);
}
}
if ( ! empty ( $listofemailstoadd )) {
$addr_bcc .= ( $addr_bcc ? ', ' : '' ) . join ( ', ' , $listofemailstoadd );
}
2020-12-08 08:49:06 +01:00
}
2022-02-28 14:10:35 +01:00
$this -> subject = $subject ;
2022-11-28 15:37:38 +01:00
$this -> addr_to = dol_sanitizeEmail ( $to );
$this -> addr_from = dol_sanitizeEmail ( $from );
2022-02-28 14:10:35 +01:00
$this -> msg = $msg ;
2022-11-28 15:37:38 +01:00
$this -> addr_cc = dol_sanitizeEmail ( $addr_cc );
$this -> addr_bcc = dol_sanitizeEmail ( $addr_bcc );
2022-02-28 14:10:35 +01:00
$this -> deliveryreceipt = $deliveryreceipt ;
if ( empty ( $replyto )) {
2022-11-28 16:57:06 +01:00
$replyto = dol_sanitizeEmail ( $from );
2022-02-28 14:10:35 +01:00
}
2022-11-28 16:57:06 +01:00
$this -> reply_to = dol_sanitizeEmail ( $replyto );
$this -> errors_to = dol_sanitizeEmail ( $errors_to );
2020-08-06 16:28:17 +02:00
$this -> trackid = $trackid ;
2022-10-23 17:14:23 +02:00
// Set arrays with attached files info
2022-02-28 14:10:35 +01:00
$this -> filename_list = $filename_list ;
$this -> mimetype_list = $mimetype_list ;
$this -> mimefilename_list = $mimefilename_list ;
2022-10-23 17:14:23 +02:00
$this -> cid_list = $cid_list ;
2020-08-06 16:28:17 +02:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_FORCE_SENDTO )) {
2022-11-28 15:37:38 +01:00
$this -> addr_to = dol_sanitizeEmail ( $conf -> global -> MAIN_MAIL_FORCE_SENDTO );
2020-08-06 16:28:17 +02:00
$this -> addr_cc = '' ;
$this -> addr_bcc = '' ;
}
2020-10-31 14:32:18 +01:00
$keyforsslseflsigned = 'MAIN_MAIL_EMAIL_SMTP_ALLOW_SELF_SIGNED' ;
2020-09-08 14:48:50 +02:00
if ( ! empty ( $this -> sendcontext )) {
$smtpContextKey = strtoupper ( $this -> sendcontext );
2022-08-31 14:02:09 +02:00
$smtpContextSendMode = getDolGlobalString ( 'MAIN_MAIL_SENDMODE_' . $smtpContextKey );
2020-09-08 14:48:50 +02:00
if ( ! empty ( $smtpContextSendMode ) && $smtpContextSendMode != 'default' ) {
2020-10-31 14:32:18 +01:00
$keyforsslseflsigned = 'MAIN_MAIL_EMAIL_SMTP_ALLOW_SELF_SIGNED_' . $smtpContextKey ;
2020-09-08 14:48:50 +02:00
}
}
2023-02-16 21:44:38 +01:00
dol_syslog ( " CMailFile::CMailfile: sendmode= " . $this -> sendmode . " addr_bcc= $addr_bcc , replyto= $replyto " , LOG_DEBUG );
2023-02-15 22:10:03 +01:00
2019-11-14 10:01:05 +01:00
// We set all data according to choosed sending method.
// We also set a value for ->msgid
2021-01-16 14:12:09 +01:00
if ( $this -> sendmode == 'mail' ) {
2009-02-09 01:04:34 +01:00
// Use mail php function (default PHP method)
// ------------------------------------------
$smtp_headers = " " ;
$mime_headers = " " ;
$text_body = " " ;
2011-03-25 19:12:58 +01:00
$files_encoded = " " ;
2009-02-09 01:04:34 +01:00
2019-11-14 10:01:05 +01:00
// Define smtp_headers (this also set ->msgid)
2009-02-09 01:04:34 +01:00
$smtp_headers = $this -> write_smtpheaders ();
2021-01-16 14:12:09 +01:00
if ( ! empty ( $moreinheader )) {
$smtp_headers .= $moreinheader ; // $moreinheader contains the \r\n
}
2017-01-11 16:47:17 +01:00
2009-05-18 00:54:12 +02:00
// Define mime_headers
2012-02-10 13:28:53 +01:00
$mime_headers = $this -> write_mimeheaders ( $filename_list , $mimefilename_list );
2009-05-13 16:49:30 +02:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $this -> html )) {
if ( ! empty ( $css )) {
2009-11-18 13:31:55 +01:00
$this -> css = $css ;
2019-11-13 18:32:11 +01:00
$this -> buildCSS (); // Build a css style (mode = all) into this->styleCSS and this->bodyCSS
2009-11-18 13:31:55 +01:00
}
2010-01-13 00:03:34 +01:00
2009-11-18 13:31:55 +01:00
$msg = $this -> html ;
}
2006-11-01 00:10:46 +01:00
2009-05-18 00:54:12 +02:00
// Define body in text_body
2009-05-13 21:10:06 +02:00
$text_body = $this -> write_body ( $msg );
2009-05-18 00:54:12 +02:00
// Add attachments to text_encoded
2020-12-01 11:35:30 +01:00
if ( ! empty ( $this -> atleastonefile )) {
2022-10-23 17:14:23 +02:00
$files_encoded = $this -> write_files ( $filename_list , $mimetype_list , $mimefilename_list , $cid_list );
2009-02-09 01:04:34 +01:00
}
2008-11-15 01:52:42 +01:00
2012-02-01 20:44:06 +01:00
// We now define $this->headers and $this->message
2019-11-13 18:32:11 +01:00
$this -> headers = $smtp_headers . $mime_headers ;
2009-02-09 01:04:34 +01:00
// On nettoie le header pour qu'il ne se termine pas par un retour chariot.
2019-06-29 16:29:32 +02:00
// This avoid also empty lines at end that can be interpreted as mail injection by email servers.
2019-01-27 11:55:16 +01:00
$this -> headers = preg_replace ( " /([ \r \n ]+) $ /i " , " " , $this -> headers );
2012-02-01 20:44:06 +01:00
2017-10-16 14:31:28 +02:00
//$this->message = $this->eol.'This is a message with multiple parts in MIME format.'.$this->eol;
$this -> message = 'This is a message with multiple parts in MIME format.' . $this -> eol ;
2019-11-13 18:32:11 +01:00
$this -> message .= $text_body . $files_encoded ;
$this -> message .= " -- " . $this -> mixed_boundary . " -- " . $this -> eol ;
2021-01-16 14:12:09 +01:00
} elseif ( $this -> sendmode == 'smtps' ) {
2009-02-09 01:04:34 +01:00
// Use SMTPS library
// ------------------------------------------
2012-08-22 23:11:24 +02:00
require_once DOL_DOCUMENT_ROOT . '/core/class/smtps.class.php' ;
2009-02-09 01:04:34 +01:00
$smtps = new SMTPs ();
2009-05-08 03:11:04 +02:00
$smtps -> setCharSet ( $conf -> file -> character_set_client );
2009-05-13 16:49:30 +02:00
2020-02-06 12:58:02 +01:00
// Encode subject if required.
2020-08-06 16:54:49 +02:00
$subjecttouse = $this -> subject ;
2020-04-10 10:59:32 +02:00
if ( ! ascii_check ( $subjecttouse )) {
2020-02-06 12:58:02 +01:00
$subjecttouse = $this -> encodetorfc2822 ( $subjecttouse );
}
$smtps -> setSubject ( $subjecttouse );
2020-08-07 17:06:57 +02:00
$smtps -> setTO ( $this -> getValidAddress ( $this -> addr_to , 0 , 1 ));
2020-08-07 17:06:12 +02:00
$smtps -> setFrom ( $this -> getValidAddress ( $this -> addr_from , 0 , 1 ));
2020-08-06 16:28:17 +02:00
$smtps -> setTrackId ( $this -> trackid );
2020-08-31 17:07:13 +02:00
$smtps -> setReplyTo ( $this -> getValidAddress ( $this -> reply_to , 0 , 1 ));
2017-01-11 16:47:17 +01:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $moreinheader )) {
$smtps -> setMoreInHeader ( $moreinheader );
}
2017-01-12 11:06:24 +01:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $this -> html )) {
if ( ! empty ( $css )) {
2009-05-19 17:40:25 +02:00
$this -> css = $css ;
2013-03-15 18:27:48 +01:00
$this -> buildCSS ();
2009-05-19 17:40:25 +02:00
}
2009-05-13 16:49:30 +02:00
$msg = $this -> html ;
$msg = $this -> checkIfHTML ( $msg );
}
2020-02-09 15:51:43 +01:00
// Replace . alone on a new line with .. to avoid to have SMTP interpret this as end of message
$msg = preg_replace ( '/(\r|\n)\.(\r|\n)/ims' , '\1..\2' , $msg );
2021-01-16 14:12:09 +01:00
if ( $this -> msgishtml ) {
$smtps -> setBodyContent ( $msg , 'html' );
} else {
$smtps -> setBodyContent ( $msg , 'plain' );
}
2009-02-09 01:04:34 +01:00
2021-01-16 14:12:09 +01:00
if ( $this -> atleastoneimage ) {
foreach ( $this -> images_encoded as $img ) {
2019-01-27 11:55:16 +01:00
$smtps -> setImageInline ( $img [ 'image_encoded' ], $img [ 'name' ], $img [ 'content_type' ], $img [ 'cid' ]);
2009-05-11 19:13:56 +02:00
}
}
2009-05-13 16:49:30 +02:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $this -> atleastonefile )) {
foreach ( $filename_list as $i => $val ) {
2019-11-13 18:32:11 +01:00
$content = file_get_contents ( $filename_list [ $i ]);
2022-10-23 17:14:23 +02:00
$smtps -> setAttachment ( $content , $mimefilename_list [ $i ], $mimetype_list [ $i ], $cid_list [ $i ]);
2009-02-09 01:04:34 +01:00
}
}
2020-08-06 16:28:17 +02:00
$smtps -> setCC ( $this -> addr_cc );
$smtps -> setBCC ( $this -> addr_bcc );
$smtps -> setErrorsTo ( $this -> errors_to );
$smtps -> setDeliveryReceipt ( $this -> deliveryreceipt );
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> $keyforsslseflsigned )) {
$smtps -> setOptions ( array ( 'ssl' => array ( 'verify_peer' => false , 'verify_peer_name' => false , 'allow_self_signed' => true )));
}
2009-02-09 01:04:34 +01:00
2020-04-10 10:59:32 +02:00
$host = dol_getprefix ( 'email' );
2020-08-07 17:11:23 +02:00
$this -> msgid = time () . '.SMTPs-dolibarr-' . $this -> trackid . '@' . $host ;
2019-11-14 10:01:05 +01:00
2019-11-13 18:32:11 +01:00
$this -> smtps = $smtps ;
2020-08-07 11:59:55 +02:00
} elseif ( $this -> sendmode == 'swiftmailer' ) {
2017-04-18 01:39:06 +02:00
// Use Swift Mailer library
2020-09-07 10:18:17 +02:00
$host = dol_getprefix ( 'email' );
require_once DOL_DOCUMENT_ROOT . '/includes/swiftmailer/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php' ;
// egulias autoloader lib
require_once DOL_DOCUMENT_ROOT . '/includes/swiftmailer/autoload.php' ;
require_once DOL_DOCUMENT_ROOT . '/includes/swiftmailer/lib/swift_required.php' ;
// Create the message
//$this->message = Swift_Message::newInstance();
$this -> message = new Swift_Message ();
//$this->message = new Swift_SignedMessage();
// Adding a trackid header to a message
$headers = $this -> message -> getHeaders ();
$headers -> addTextHeader ( 'X-Dolibarr-TRACKID' , $this -> trackid . '@' . $host );
$this -> msgid = time () . '.swiftmailer-dolibarr-' . $this -> trackid . '@' . $host ;
$headerID = $this -> msgid ;
$msgid = $headers -> get ( 'Message-ID' );
$msgid -> setId ( $headerID );
$headers -> addIdHeader ( 'References' , $headerID );
2022-08-31 22:14:20 +02:00
// TODO if (!empty($moreinheader)) ...
2020-09-07 10:18:17 +02:00
// Give the message a subject
try {
$result = $this -> message -> setSubject ( $this -> subject );
} catch ( Exception $e ) {
$this -> errors [] = $e -> getMessage ();
}
// Set the From address with an associative array
//$this->message->setFrom(array('john@doe.com' => 'John Doe'));
2020-09-08 21:27:28 +02:00
if ( ! empty ( $this -> addr_from )) {
2020-09-07 10:18:17 +02:00
try {
2020-09-08 21:27:28 +02:00
if ( ! empty ( $conf -> global -> MAIN_FORCE_DISABLE_MAIL_SPOOFING )) {
2020-07-06 12:00:14 +02:00
// Prevent email spoofing for smtp server with a strict configuration
$regexp = '/([a-z0-9_\.\-\+])+\@(([a-z0-9\-])+\.)+([a-z0-9]{2,4})+/i' ; // This regular expression extracts all emails from a string
2022-10-23 17:14:23 +02:00
$adressEmailFrom = array ();
2020-07-06 12:00:14 +02:00
$emailMatchs = preg_match_all ( $regexp , $from , $adressEmailFrom );
$adressEmailFrom = reset ( $adressEmailFrom );
2021-01-16 14:12:09 +01:00
if ( $emailMatchs !== false && filter_var ( $conf -> global -> MAIN_MAIL_SMTPS_ID , FILTER_VALIDATE_EMAIL ) && $conf -> global -> MAIN_MAIL_SMTPS_ID !== $adressEmailFrom ) {
2022-08-04 09:24:57 +02:00
$this -> message -> setFrom ( $conf -> global -> MAIN_MAIL_SMTPS_ID );
2020-07-06 12:01:00 +02:00
} else {
2022-08-04 09:24:57 +02:00
$this -> message -> setFrom ( $this -> getArrayAddress ( $this -> addr_from ));
2020-07-06 12:00:14 +02:00
}
} else {
2022-08-04 09:24:57 +02:00
$this -> message -> setFrom ( $this -> getArrayAddress ( $this -> addr_from ));
2020-07-01 16:55:23 +02:00
}
2020-09-07 10:18:17 +02:00
} catch ( Exception $e ) {
$this -> errors [] = $e -> getMessage ();
}
}
// Set the To addresses with an associative array
2020-09-08 21:27:28 +02:00
if ( ! empty ( $this -> addr_to )) {
2020-09-07 10:18:17 +02:00
try {
2022-08-04 09:24:57 +02:00
$this -> message -> setTo ( $this -> getArrayAddress ( $this -> addr_to ));
2020-09-07 10:18:17 +02:00
} catch ( Exception $e ) {
$this -> errors [] = $e -> getMessage ();
}
}
2020-09-08 21:27:28 +02:00
if ( ! empty ( $this -> reply_to )) {
2020-09-07 10:18:17 +02:00
try {
2022-08-04 09:24:57 +02:00
$this -> message -> SetReplyTo ( $this -> getArrayAddress ( $this -> reply_to ));
2020-09-07 10:18:17 +02:00
} catch ( Exception $e ) {
$this -> errors [] = $e -> getMessage ();
}
}
try {
2022-08-04 09:24:57 +02:00
$this -> message -> setCharSet ( $conf -> file -> character_set_client );
2020-09-07 10:18:17 +02:00
} catch ( Exception $e ) {
$this -> errors [] = $e -> getMessage ();
}
if ( ! empty ( $this -> html )) {
2019-03-02 14:32:52 +01:00
if ( ! empty ( $css )) {
2017-04-18 01:39:06 +02:00
$this -> css = $css ;
$this -> buildCSS ();
}
$msg = $this -> html ;
$msg = $this -> checkIfHTML ( $msg );
}
2021-01-16 14:12:09 +01:00
if ( $this -> atleastoneimage ) {
foreach ( $this -> images_encoded as $img ) {
2017-04-18 01:39:06 +02:00
//$img['fullpath'],$img['image_encoded'],$img['name'],$img['content_type'],$img['cid']
2019-09-06 10:36:49 +02:00
$attachment = Swift_Image :: fromPath ( $img [ 'fullpath' ]);
2017-04-18 01:39:06 +02:00
// embed image
$imgcid = $this -> message -> embed ( $attachment );
// replace cid by the one created by swiftmail in html message
$msg = str_replace ( " cid: " . $img [ 'cid' ], $imgcid , $msg );
}
}
if ( $this -> msgishtml ) {
2019-01-27 11:55:16 +01:00
$this -> message -> setBody ( $msg , 'text/html' );
2017-04-18 01:39:06 +02:00
// And optionally an alternative body
2018-01-21 15:55:56 +01:00
$this -> message -> addPart ( html_entity_decode ( strip_tags ( $msg )), 'text/plain' );
2017-04-18 01:39:06 +02:00
} else {
2019-01-27 11:55:16 +01:00
$this -> message -> setBody ( $msg , 'text/plain' );
2017-04-18 01:39:06 +02:00
// And optionally an alternative body
2019-12-22 09:13:34 +01:00
$this -> message -> addPart ( dol_nl2br ( $msg ), 'text/html' );
2017-04-18 01:39:06 +02:00
}
2021-01-16 14:12:09 +01:00
if ( ! empty ( $this -> atleastonefile )) {
foreach ( $filename_list as $i => $val ) {
2017-04-18 01:39:06 +02:00
//$this->message->attach(Swift_Attachment::fromPath($filename_list[$i],$mimetype_list[$i]));
2019-01-27 11:55:16 +01:00
$attachment = Swift_Attachment :: fromPath ( $filename_list [ $i ], $mimetype_list [ $i ]);
2020-09-01 15:36:35 +02:00
if ( ! empty ( $mimefilename_list [ $i ])) {
$attachment -> setFilename ( $mimefilename_list [ $i ]);
}
2017-04-18 01:39:06 +02:00
$this -> message -> attach ( $attachment );
}
}
2021-01-16 14:12:09 +01:00
if ( ! empty ( $this -> addr_cc )) {
2022-08-02 11:01:09 +02:00
try {
$this -> message -> setCc ( $this -> getArrayAddress ( $this -> addr_cc ));
} catch ( Exception $e ) {
$this -> errors [] = $e -> getMessage ();
}
2021-01-16 14:12:09 +01:00
}
if ( ! empty ( $this -> addr_bcc )) {
2022-08-02 11:01:09 +02:00
try {
$this -> message -> setBcc ( $this -> getArrayAddress ( $this -> addr_bcc ));
} catch ( Exception $e ) {
$this -> errors [] = $e -> getMessage ();
}
2021-01-16 14:12:09 +01:00
}
2022-08-31 22:14:20 +02:00
//if (!empty($this->errors_to)) $this->message->setErrorsTo($this->getArrayAddress($this->errors_to));
2021-01-16 14:12:09 +01:00
if ( isset ( $this -> deliveryreceipt ) && $this -> deliveryreceipt == 1 ) {
2022-08-04 09:24:57 +02:00
try {
$this -> message -> setReadReceiptTo ( $this -> getArrayAddress ( $this -> addr_from ));
} catch ( Exception $e ) {
$this -> errors [] = $e -> getMessage ();
}
2021-01-16 14:12:09 +01:00
}
2020-05-21 15:05:19 +02:00
} else {
2009-02-09 01:04:34 +01:00
// Send mail method not correctly defined
// --------------------------------------
2017-04-18 01:39:06 +02:00
$this -> error = 'Bad value for sendmode' ;
2008-11-15 01:52:42 +01:00
}
}
2009-02-09 01:04:34 +01:00
2008-11-15 01:52:42 +01:00
/**
2018-02-03 17:32:38 +01:00
* Send mail that was prepared by constructor .
2010-01-13 00:03:34 +01:00
*
2009-11-17 23:00:30 +01:00
* @ return boolean True if mail sent , false otherwise
2008-11-15 01:52:42 +01:00
*/
2019-02-25 22:27:04 +01:00
public function sendfile ()
2007-06-07 23:24:01 +02:00
{
2023-03-26 17:59:28 +02:00
global $conf , $db , $langs , $hookmanager ;
2008-11-15 01:52:42 +01:00
2019-11-13 18:32:11 +01:00
$errorlevel = error_reporting ();
2018-01-21 15:55:56 +01:00
//error_reporting($errorlevel ^ E_WARNING); // Desactive warnings
2006-08-06 20:34:37 +02:00
2019-11-13 18:32:11 +01:00
$res = false ;
2008-11-15 01:52:42 +01:00
2021-01-16 14:12:09 +01:00
if ( empty ( $conf -> global -> MAIN_DISABLE_ALL_MAILS )) {
2023-03-26 17:59:28 +02:00
if ( ! is_object ( $hookmanager )) {
include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php' ;
$hookmanager = new HookManager ( $db );
}
2018-02-03 17:32:38 +01:00
$hookmanager -> initHooks ( array ( 'mail' ));
2021-03-01 20:37:16 +01:00
$parameters = array ();
$action = '' ;
2018-02-03 17:32:38 +01:00
$reshook = $hookmanager -> executeHooks ( 'sendMail' , $parameters , $this , $action ); // Note that $action and $object may have been modified by some hooks
2021-01-16 14:12:09 +01:00
if ( $reshook < 0 ) {
2019-11-13 18:32:11 +01:00
$this -> error = " Error in hook maildao sendMail " . $reshook ;
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_ERR );
2017-04-18 01:39:06 +02:00
return $reshook ;
}
2021-01-16 14:12:09 +01:00
if ( $reshook == 1 ) { // Hook replace standard code
2018-02-03 17:32:38 +01:00
return true ;
}
2017-04-18 01:39:06 +02:00
2019-05-21 21:16:06 +02:00
$sendingmode = $this -> sendmode ;
2022-05-20 17:14:30 +02:00
if ( $this -> sendcontext == 'emailing' && ! empty ( $conf -> global -> MAILING_NO_USING_PHPMAIL ) && $sendingmode == 'mail' ) {
2020-09-07 10:18:17 +02:00
// List of sending methods
$listofmethods = array ();
$listofmethods [ 'mail' ] = 'PHP mail function' ;
//$listofmethods['simplemail']='Simplemail class';
$listofmethods [ 'smtps' ] = 'SMTP/SMTPS socket library' ;
// EMailing feature may be a spam problem, so when you host several users/instance, having this option may force each user to use their own SMTP agent.
// You ensure that every user is using its own SMTP server when using the mass emailing module.
$linktoadminemailbefore = '<a href="' . DOL_URL_ROOT . '/admin/mails.php">' ;
$linktoadminemailend = '</a>' ;
$this -> error = $langs -> trans ( " MailSendSetupIs " , $listofmethods [ $sendingmode ]);
$this -> errors [] = $langs -> trans ( " MailSendSetupIs " , $listofmethods [ $sendingmode ]);
$this -> error .= '<br>' . $langs -> trans ( " MailSendSetupIs2 " , $linktoadminemailbefore , $linktoadminemailend , $langs -> transnoentitiesnoconv ( " MAIN_MAIL_SENDMODE " ), $listofmethods [ 'smtps' ]);
$this -> errors [] = $langs -> trans ( " MailSendSetupIs2 " , $linktoadminemailbefore , $linktoadminemailend , $langs -> transnoentitiesnoconv ( " MAIN_MAIL_SENDMODE " ), $listofmethods [ 'smtps' ]);
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAILING_SMTP_SETUP_EMAILS_FOR_QUESTIONS )) {
2020-09-07 10:18:17 +02:00
$this -> error .= '<br>' . $langs -> trans ( " MailSendSetupIs3 " , $conf -> global -> MAILING_SMTP_SETUP_EMAILS_FOR_QUESTIONS );
$this -> errors [] = $langs -> trans ( " MailSendSetupIs3 " , $conf -> global -> MAILING_SMTP_SETUP_EMAILS_FOR_QUESTIONS );
}
2023-03-23 11:14:22 +01:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_WARNING );
2020-09-07 10:18:17 +02:00
return false ;
2019-05-21 21:16:06 +02:00
}
2017-04-18 01:39:06 +02:00
// Check number of recipient is lower or equal than MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL
2021-01-16 14:12:09 +01:00
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 ;
}
2017-04-18 01:39:06 +02:00
$tmparray1 = explode ( ',' , $this -> addr_to );
2021-01-16 14:12:09 +01:00
if ( count ( $tmparray1 ) > $conf -> global -> MAIL_MAX_NB_OF_RECIPIENTS_TO_IN_SAME_EMAIL ) {
2017-04-18 01:39:06 +02:00
$this -> error = 'Too much recipients in to:' ;
2019-11-13 18:32:11 +01:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_WARNING );
2017-04-18 01:39:06 +02:00
return false ;
}
2021-01-16 14:12:09 +01:00
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 ;
}
2017-04-18 01:39:06 +02:00
$tmparray2 = explode ( ',' , $this -> addr_cc );
2021-01-16 14:12:09 +01:00
if ( count ( $tmparray2 ) > $conf -> global -> MAIL_MAX_NB_OF_RECIPIENTS_CC_IN_SAME_EMAIL ) {
2017-04-18 01:39:06 +02:00
$this -> error = 'Too much recipients in cc:' ;
2019-11-13 18:32:11 +01:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_WARNING );
2017-04-18 01:39:06 +02:00
return false ;
}
2021-01-16 14:12:09 +01:00
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 ;
}
2017-04-18 01:39:06 +02:00
$tmparray3 = explode ( ',' , $this -> addr_bcc );
2021-01-16 14:12:09 +01:00
if ( count ( $tmparray3 ) > $conf -> global -> MAIL_MAX_NB_OF_RECIPIENTS_BCC_IN_SAME_EMAIL ) {
2017-04-18 01:39:06 +02:00
$this -> error = 'Too much recipients in bcc:' ;
2019-11-13 18:32:11 +01:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_WARNING );
2017-04-18 01:39:06 +02:00
return false ;
}
2021-01-16 14:12:09 +01:00
if ( empty ( $conf -> global -> MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL )) {
$conf -> global -> MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL = 10 ;
}
if (( count ( $tmparray1 ) + count ( $tmparray2 ) + count ( $tmparray3 )) > $conf -> global -> MAIL_MAX_NB_OF_RECIPIENTS_IN_SAME_EMAIL ) {
2017-04-18 01:39:06 +02:00
$this -> error = 'Too much recipients in to:, cc:, bcc:' ;
2019-11-13 18:32:11 +01:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_WARNING );
2017-04-18 01:39:06 +02:00
return false ;
}
2017-01-11 16:47:17 +01:00
2019-11-13 18:32:11 +01:00
$keyforsmtpserver = 'MAIN_MAIL_SMTP_SERVER' ;
$keyforsmtpport = 'MAIN_MAIL_SMTP_PORT' ;
$keyforsmtpid = 'MAIN_MAIL_SMTPS_ID' ;
$keyforsmtppw = 'MAIN_MAIL_SMTPS_PW' ;
2022-08-26 15:21:35 +02:00
$keyforsmtpauthtype = 'MAIN_MAIL_SMTPS_AUTH_TYPE' ;
$keyforsmtpoauthservice = 'MAIN_MAIL_SMTPS_OAUTH_SERVICE' ;
2019-11-13 18:32:11 +01:00
$keyfortls = 'MAIN_MAIL_EMAIL_TLS' ;
$keyforstarttls = 'MAIN_MAIL_EMAIL_STARTTLS' ;
2020-10-31 14:32:18 +01:00
$keyforsslseflsigned = 'MAIN_MAIL_EMAIL_SMTP_ALLOW_SELF_SIGNED' ;
2020-09-02 15:33:18 +02:00
if ( ! empty ( $this -> sendcontext )) {
$smtpContextKey = strtoupper ( $this -> sendcontext );
2022-08-31 14:02:09 +02:00
$smtpContextSendMode = getDolGlobalString ( 'MAIN_MAIL_SENDMODE_' . $smtpContextKey );
2020-09-02 15:33:18 +02:00
if ( ! empty ( $smtpContextSendMode ) && $smtpContextSendMode != 'default' ) {
2020-10-31 14:32:18 +01:00
$keyforsmtpserver = 'MAIN_MAIL_SMTP_SERVER_' . $smtpContextKey ;
$keyforsmtpport = 'MAIN_MAIL_SMTP_PORT_' . $smtpContextKey ;
$keyforsmtpid = 'MAIN_MAIL_SMTPS_ID_' . $smtpContextKey ;
$keyforsmtppw = 'MAIN_MAIL_SMTPS_PW_' . $smtpContextKey ;
2022-08-26 15:21:35 +02:00
$keyforsmtpauthtype = 'MAIN_MAIL_SMTPS_AUTH_TYPE_' . $smtpContextKey ;
$keyforsmtpoauthservice = 'MAIN_MAIL_SMTPS_OAUTH_SERVICE_' . $smtpContextKey ;
2020-10-31 14:32:18 +01:00
$keyfortls = 'MAIN_MAIL_EMAIL_TLS_' . $smtpContextKey ;
$keyforstarttls = 'MAIN_MAIL_EMAIL_STARTTLS_' . $smtpContextKey ;
$keyforsslseflsigned = 'MAIN_MAIL_EMAIL_SMTP_ALLOW_SELF_SIGNED_' . $smtpContextKey ;
2020-09-02 15:33:18 +02:00
}
2017-08-24 02:02:00 +02:00
}
2009-02-09 01:04:34 +01:00
// Action according to choosed sending method
2021-01-16 14:12:09 +01:00
if ( $this -> sendmode == 'mail' ) {
2009-02-09 01:04:34 +01:00
// Use mail php function (default PHP method)
// ------------------------------------------
2009-02-20 23:53:15 +01:00
dol_syslog ( " CMailFile::sendfile addr_to= " . $this -> addr_to . " , subject= " . $this -> subject , LOG_DEBUG );
2023-03-23 10:54:25 +01:00
//dol_syslog("CMailFile::sendfile header=\n".$this->headers, LOG_DEBUG);
2009-02-20 23:53:15 +01:00
//dol_syslog("CMailFile::sendfile message=\n".$message);
2009-02-09 01:04:34 +01:00
2009-05-18 00:54:12 +02:00
// If Windows, sendmail_from must be defined
2021-01-16 14:12:09 +01:00
if ( isset ( $_SERVER [ " WINDIR " ])) {
if ( empty ( $this -> addr_from )) {
$this -> addr_from = 'robot@example.com' ;
}
2019-01-27 11:55:16 +01:00
@ ini_set ( 'sendmail_from' , $this -> getValidAddress ( $this -> addr_from , 2 ));
2009-02-09 01:04:34 +01:00
}
2017-08-24 02:02:00 +02:00
// Force parameters
2019-11-21 21:36:03 +01:00
//dol_syslog("CMailFile::sendfile conf->global->".$keyforsmtpserver."=".$conf->global->$keyforsmtpserver." cpnf->global->".$keyforsmtpport."=".$conf->global->$keyforsmtpport, LOG_DEBUG);
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> $keyforsmtpserver )) {
ini_set ( 'SMTP' , $conf -> global -> $keyforsmtpserver );
}
if ( ! empty ( $conf -> global -> $keyforsmtpport )) {
ini_set ( 'smtp_port' , $conf -> global -> $keyforsmtpport );
}
2009-02-09 01:04:34 +01:00
2019-11-13 18:32:11 +01:00
$res = true ;
2021-01-16 14:12:09 +01:00
if ( $res && ! $this -> subject ) {
2019-11-13 18:32:11 +01:00
$this -> error = " Failed to send mail with php mail to HOST= " . ini_get ( 'SMTP' ) . " , PORT= " . ini_get ( 'smtp_port' ) . " <br>Subject is empty " ;
2018-02-28 19:09:05 +01:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_ERR );
2019-11-13 18:32:11 +01:00
$res = false ;
2018-02-28 19:09:05 +01:00
}
2019-11-13 18:32:11 +01:00
$dest = $this -> getValidAddress ( $this -> addr_to , 2 );
2021-01-16 14:12:09 +01:00
if ( $res && ! $dest ) {
2019-11-13 18:32:11 +01:00
$this -> error = " Failed to send mail with php mail to HOST= " . ini_get ( 'SMTP' ) . " , PORT= " . ini_get ( 'smtp_port' ) . " <br>Recipient address ' $dest ' invalid " ;
2011-11-01 13:22:39 +01:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_ERR );
2019-11-13 18:32:11 +01:00
$res = false ;
2009-02-09 01:04:34 +01:00
}
2018-02-28 19:09:05 +01:00
2021-01-16 14:12:09 +01:00
if ( $res ) {
2019-11-13 18:32:11 +01:00
$additionnalparam = '' ; // By default
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_ALLOW_SENDMAIL_F )) {
2015-06-26 13:18:40 +02:00
// le "Return-Path" (retour des messages bounced) dans les header ne fonctionne pas avec tous les MTA
2016-04-16 18:15:03 +02:00
// Le forcage de la valeur grace à l'option -f de sendmail est donc possible si la constante MAIN_MAIL_ALLOW_SENDMAIL_F est definie.
2016-12-26 00:00:28 +01:00
// Having this variable defined may create problems with some sendmail (option -f refused)
// Having this variable not defined may create problems with some other sendmail (option -f required)
2019-11-13 18:32:11 +01:00
$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 ) : '' ));
2009-02-09 01:04:34 +01:00
}
2021-01-16 14:12:09 +01:00
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
2019-11-13 18:32:11 +01:00
$additionnalparam .= ( $additionnalparam ? ' ' : '' ) . '-ba' ;
2017-04-18 01:39:06 +02:00
}
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_SENDMAIL_FORCE_ADDPARAM )) {
$additionnalparam .= ( $additionnalparam ? ' ' : '' ) . '-U ' . $additionnalparam ; // Use -U to add additionnal params
}
2017-04-18 01:39:06 +02:00
2020-12-13 18:32:55 +01:00
$linuxlike = 1 ;
2021-01-16 14:12:09 +01:00
if ( preg_match ( '/^win/i' , PHP_OS )) {
$linuxlike = 0 ;
}
if ( preg_match ( '/^mac/i' , PHP_OS )) {
$linuxlike = 0 ;
}
2020-12-13 18:32:55 +01:00
dol_syslog ( " CMailFile::sendfile: mail start " . ( $linuxlike ? '' : " HOST= " . ini_get ( 'SMTP' ) . " , PORT= " . ini_get ( 'smtp_port' )) . " , additionnal_parameters= " . $additionnalparam , LOG_DEBUG );
2017-04-18 01:39:06 +02:00
2019-11-13 18:32:11 +01:00
$this -> message = stripslashes ( $this -> message );
2009-05-13 21:10:06 +02:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_DEBUG )) {
$this -> dump_mail ();
}
2009-05-13 21:10:06 +02:00
2020-02-06 12:58:02 +01:00
// Encode subject if required.
$subjecttouse = $this -> subject ;
2020-04-10 10:59:32 +02:00
if ( ! ascii_check ( $subjecttouse )) {
2020-02-06 12:58:02 +01:00
$subjecttouse = $this -> encodetorfc2822 ( $subjecttouse );
}
2021-01-16 14:12:09 +01:00
if ( ! empty ( $additionnalparam )) {
$res = mail ( $dest , $subjecttouse , $this -> message , $this -> headers , $additionnalparam );
} else {
$res = mail ( $dest , $subjecttouse , $this -> message , $this -> headers );
}
2009-05-24 22:01:25 +02:00
2021-01-16 14:12:09 +01:00
if ( ! $res ) {
2018-06-29 18:23:59 +02:00
$langs -> load ( " errors " );
2019-11-13 18:32:11 +01:00
$this -> error = " Failed to send mail with php mail " ;
2020-12-13 18:32:55 +01:00
if ( ! $linuxlike ) {
2019-11-13 18:32:11 +01:00
$this -> error .= " to HOST= " . ini_get ( 'SMTP' ) . " , PORT= " . ini_get ( 'smtp_port' ); // This values are value used only for non linuxlike systems
2015-06-26 13:18:40 +02:00
}
2019-11-13 18:32:11 +01:00
$this -> error .= " .<br> " ;
$this -> error .= $langs -> trans ( " ErrorPhpMailDelivery " );
2011-11-01 13:22:39 +01:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_ERR );
2023-03-02 10:38:45 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_DEBUG )) {
2023-03-30 14:48:04 +02:00
$this -> save_dump_mail_in_err ( 'Mail with topic ' . $this -> subject );
2023-03-02 10:38:45 +01:00
}
2020-05-21 15:05:19 +02:00
} else {
2009-05-24 22:01:25 +02:00
dol_syslog ( " CMailFile::sendfile: mail end success " , LOG_DEBUG );
2009-05-18 00:54:12 +02:00
}
2009-05-24 22:01:25 +02:00
}
2021-01-16 14:12:09 +01:00
if ( isset ( $_SERVER [ " WINDIR " ])) {
2009-05-24 22:01:25 +02:00
@ ini_restore ( 'sendmail_from' );
}
2017-08-24 02:02:00 +02:00
// Restore parameters
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> $keyforsmtpserver )) {
ini_restore ( 'SMTP' );
}
if ( ! empty ( $conf -> global -> $keyforsmtpport )) {
ini_restore ( 'smtp_port' );
}
} elseif ( $this -> sendmode == 'smtps' ) {
if ( ! is_object ( $this -> smtps )) {
2019-11-13 18:32:11 +01:00
$this -> error = " Failed to send mail with smtps lib to HOST= " . $server . " , PORT= " . $conf -> global -> $keyforsmtpport . " <br>Constructor of object CMailFile was not initialized without errors. " ;
2018-06-19 01:15:37 +02:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_ERR );
return false ;
}
2009-02-09 01:04:34 +01:00
// Use SMTPS library
// ------------------------------------------
2019-11-13 18:32:11 +01:00
$this -> smtps -> setTransportType ( 0 ); // Only this method is coded in SMTPs library
2009-02-09 01:04:34 +01:00
2017-04-11 10:57:17 +02:00
// Clean parameters
2021-01-16 14:12:09 +01:00
if ( empty ( $conf -> global -> $keyforsmtpserver )) {
$conf -> global -> $keyforsmtpserver = ini_get ( 'SMTP' );
}
if ( empty ( $conf -> global -> $keyforsmtpport )) {
$conf -> global -> $keyforsmtpport = ini_get ( 'smtp_port' );
}
2017-04-18 01:39:06 +02:00
2009-11-01 15:16:30 +01:00
// If we use SSL/TLS
2019-11-13 18:32:11 +01:00
$server = $conf -> global -> $keyforsmtpserver ;
$secure = '' ;
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> $keyfortls ) && function_exists ( 'openssl_open' )) {
$secure = 'ssl' ;
}
if ( ! empty ( $conf -> global -> $keyforstarttls ) && function_exists ( 'openssl_open' )) {
$secure = 'tls' ;
}
2019-11-13 18:32:11 +01:00
$server = ( $secure ? $secure . '://' : '' ) . $server ;
2017-08-24 02:02:00 +02:00
2019-11-13 18:32:11 +01:00
$port = $conf -> global -> $keyforsmtpport ;
2017-04-18 01:39:06 +02:00
2009-11-01 15:16:30 +01:00
$this -> smtps -> setHost ( $server );
2017-04-11 10:57:17 +02:00
$this -> smtps -> setPort ( $port ); // 25, 465...;
2009-02-09 01:04:34 +01:00
2021-03-01 20:37:16 +01:00
$loginid = '' ;
$loginpass = '' ;
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> $keyforsmtpid )) {
2017-08-24 02:02:00 +02:00
$loginid = $conf -> global -> $keyforsmtpid ;
2017-04-18 01:39:06 +02:00
$this -> smtps -> setID ( $loginid );
2017-04-11 10:57:17 +02:00
}
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> $keyforsmtppw )) {
2017-08-24 02:02:00 +02:00
$loginpass = $conf -> global -> $keyforsmtppw ;
2017-04-18 01:39:06 +02:00
$this -> smtps -> setPW ( $loginpass );
2017-04-11 10:57:17 +02:00
}
2008-08-20 11:25:41 +02:00
2022-08-10 09:54:14 +02:00
if ( getDolGlobalString ( $keyforsmtpauthtype ) === " XOAUTH2 " ) {
2022-08-01 11:31:32 +02:00
require_once DOL_DOCUMENT_ROOT . '/core/lib/oauth.lib.php' ; // define $supportedoauth2array
2023-03-02 10:38:45 +01:00
2022-08-01 11:31:32 +02:00
$keyforsupportedoauth2array = $conf -> global -> $keyforsmtpoauthservice ;
if ( preg_match ( '/^.*-/' , $keyforsupportedoauth2array )) {
$keyforprovider = preg_replace ( '/^.*-/' , '' , $keyforsupportedoauth2array );
} else {
$keyforprovider = '' ;
}
$keyforsupportedoauth2array = preg_replace ( '/-.*$/' , '' , $keyforsupportedoauth2array );
$keyforsupportedoauth2array = 'OAUTH_' . $keyforsupportedoauth2array . '_NAME' ;
2022-09-10 13:58:19 +02:00
if ( isset ( $supportedoauth2array )) {
$OAUTH_SERVICENAME = ( empty ( $supportedoauth2array [ $keyforsupportedoauth2array ][ 'name' ]) ? 'Unknown' : $supportedoauth2array [ $keyforsupportedoauth2array ][ 'name' ] . ( $keyforprovider ? '-' . $keyforprovider : '' ));
} else {
$OAUTH_SERVICENAME = 'Unknown' ;
}
2022-08-01 11:31:32 +02:00
require_once DOL_DOCUMENT_ROOT . '/includes/OAuth/bootstrap.php' ;
2023-02-08 01:28:14 +01:00
$storage = new DoliStorage ( $db , $conf , $keyforprovider );
2022-08-01 11:31:32 +02:00
try {
2022-08-12 11:00:02 +02:00
$tokenobj = $storage -> retrieveAccessToken ( $OAUTH_SERVICENAME );
2022-08-12 11:42:23 +02:00
$expire = false ;
2022-08-12 11:00:02 +02:00
// Is token expired or will token expire in the next 30 seconds
if ( is_object ( $tokenobj )) {
$expire = ( $tokenobj -> getEndOfLife () !== - 9002 && $tokenobj -> getEndOfLife () !== - 9001 && time () > ( $tokenobj -> getEndOfLife () - 30 ));
}
// Token expired so we refresh it
if ( is_object ( $tokenobj ) && $expire ) {
$credentials = new Credentials (
getDolGlobalString ( 'OAUTH_' . getDolGlobalString ( 'MAIN_MAIL_SMTPS_OAUTH_SERVICE' ) . '_ID' ),
getDolGlobalString ( 'OAUTH_' . getDolGlobalString ( 'MAIN_MAIL_SMTPS_OAUTH_SERVICE' ) . '_SECRET' ),
getDolGlobalString ( 'OAUTH_' . getDolGlobalString ( 'MAIN_MAIL_SMTPS_OAUTH_SERVICE' ) . '_URLAUTHORIZE' )
);
$serviceFactory = new \OAuth\ServiceFactory ();
$oauthname = explode ( '-' , $OAUTH_SERVICENAME );
// ex service is Google-Emails we need only the first part Google
$apiService = $serviceFactory -> createService ( $oauthname [ 0 ], $credentials , $storage , array ());
// We have to save the token because Google give it only once
$refreshtoken = $tokenobj -> getRefreshToken ();
$tokenobj = $apiService -> refreshAccessToken ( $tokenobj );
$tokenobj -> setRefreshToken ( $refreshtoken );
$storage -> storeAccessToken ( $OAUTH_SERVICENAME , $tokenobj );
}
2022-08-01 11:31:32 +02:00
$tokenobj = $storage -> retrieveAccessToken ( $OAUTH_SERVICENAME );
if ( is_object ( $tokenobj )) {
$this -> smtps -> setToken ( $tokenobj -> getAccessToken ());
} else {
$this -> error = " Token not found " ;
}
} catch ( Exception $e ) {
// Return an error if token not found
$this -> error = $e -> getMessage ();
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_ERR );
}
}
2019-11-13 18:32:11 +01:00
$res = true ;
$from = $this -> smtps -> getFrom ( 'org' );
2021-01-16 14:12:09 +01:00
if ( $res && ! $from ) {
2020-08-07 17:06:12 +02:00
$this -> error = " Failed to send mail with smtps lib to HOST= " . $server . " , PORT= " . $conf -> global -> $keyforsmtpport . " - Sender address ' $from ' invalid " ;
2011-01-14 02:11:02 +01:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_ERR );
2019-11-13 18:32:11 +01:00
$res = false ;
2011-01-14 02:11:02 +01:00
}
2019-11-13 18:32:11 +01:00
$dest = $this -> smtps -> getTo ();
2021-01-16 14:12:09 +01:00
if ( $res && ! $dest ) {
2020-08-07 17:06:12 +02:00
$this -> error = " Failed to send mail with smtps lib to HOST= " . $server . " , PORT= " . $conf -> global -> $keyforsmtpport . " - Recipient address ' $dest ' invalid " ;
2009-05-24 23:30:37 +02:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_ERR );
2019-11-13 18:32:11 +01:00
$res = false ;
2007-06-07 23:24:01 +02:00
}
2011-07-02 18:48:31 +02:00
2021-01-16 14:12:09 +01:00
if ( $res ) {
2023-02-16 02:59:29 +01:00
dol_syslog ( " CMailFile::sendfile: sendMsg, HOST= " . $server . " , PORT= " . $conf -> global -> $keyforsmtpport , LOG_DEBUG );
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_DEBUG )) {
$this -> smtps -> setDebug ( true );
}
2017-08-24 02:02:00 +02:00
2019-11-13 18:32:11 +01:00
$result = $this -> smtps -> sendMsg ();
2009-02-09 01:04:34 +01:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_DEBUG )) {
$this -> dump_mail ();
}
2009-02-09 01:04:34 +01:00
2023-03-24 13:27:04 +01:00
if ( ! $result ) {
$smtperrorcode = $this -> smtps -> lastretval ; // SMTP error code
dol_syslog ( " CMailFile::sendfile: mail SMTP error code " . $smtperrorcode , LOG_WARNING );
if ( $smtperrorcode == '421' ) { // Try later
// TODO Add a delay and try again
/*
dol_syslog ( " CMailFile::sendfile: Try later error, so we wait and we retry " );
sleep ( 2 );
$result = $this -> smtps -> sendMsg ();
if ( ! empty ( $conf -> global -> MAIN_MAIL_DEBUG )) {
$this -> dump_mail ();
}
*/
}
}
$result = $this -> smtps -> getErrors (); // applicative error code (not SMTP error code)
2021-01-16 14:12:09 +01:00
if ( empty ( $this -> error ) && empty ( $result )) {
2018-10-29 03:25:21 +01:00
dol_syslog ( " CMailFile::sendfile: mail end success " , LOG_DEBUG );
2019-11-13 18:32:11 +01:00
$res = true ;
2020-05-21 15:05:19 +02:00
} else {
2021-01-16 14:12:09 +01:00
if ( empty ( $this -> error )) {
$this -> error = $result ;
}
2020-08-07 17:06:12 +02:00
dol_syslog ( " CMailFile::sendfile: mail end error with smtps lib to HOST= " . $server . " , PORT= " . $conf -> global -> $keyforsmtpport . " - " . $this -> error , LOG_ERR );
2019-11-13 18:32:11 +01:00
$res = false ;
2023-03-02 10:38:45 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_DEBUG )) {
2023-03-30 22:25:29 +02:00
$this -> save_dump_mail_in_err ( 'Mail smtp error ' . $smtperrorcode . ' with topic ' . $this -> subject );
2023-03-02 10:38:45 +01:00
}
2010-05-12 15:14:26 +02:00
}
2010-04-13 22:58:36 +02:00
}
2021-01-16 14:12:09 +01:00
} elseif ( $this -> sendmode == 'swiftmailer' ) {
2020-09-07 10:18:17 +02:00
// Use Swift Mailer library
// ------------------------------------------
require_once DOL_DOCUMENT_ROOT . '/includes/swiftmailer/lib/swift_required.php' ;
2017-04-18 01:39:06 +02:00
2017-08-24 02:02:00 +02:00
// Clean parameters
2021-01-16 14:12:09 +01:00
if ( empty ( $conf -> global -> $keyforsmtpserver )) {
$conf -> global -> $keyforsmtpserver = ini_get ( 'SMTP' );
}
if ( empty ( $conf -> global -> $keyforsmtpport )) {
$conf -> global -> $keyforsmtpport = ini_get ( 'smtp_port' );
}
2017-04-18 01:39:06 +02:00
// If we use SSL/TLS
2018-01-21 15:55:56 +01:00
$server = $conf -> global -> $keyforsmtpserver ;
$secure = '' ;
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> $keyfortls ) && function_exists ( 'openssl_open' )) {
$secure = 'ssl' ;
}
if ( ! empty ( $conf -> global -> $keyforstarttls ) && function_exists ( 'openssl_open' )) {
$secure = 'tls' ;
}
2017-04-18 01:39:06 +02:00
2018-01-21 15:55:56 +01:00
$this -> transport = new Swift_SmtpTransport ( $server , $conf -> global -> $keyforsmtpport , $secure );
2017-04-18 01:39:06 +02:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> $keyforsmtpid )) {
$this -> transport -> setUsername ( $conf -> global -> $keyforsmtpid );
}
2022-08-10 09:54:14 +02:00
if ( ! empty ( $conf -> global -> $keyforsmtppw ) && getDolGlobalString ( $keyforsmtpauthtype ) != " XOAUTH2 " ) {
2021-01-16 14:12:09 +01:00
$this -> transport -> setPassword ( $conf -> global -> $keyforsmtppw );
}
2022-08-10 09:54:14 +02:00
if ( getDolGlobalString ( $keyforsmtpauthtype ) === " XOAUTH2 " ) {
require_once DOL_DOCUMENT_ROOT . '/core/lib/oauth.lib.php' ; // define $supportedoauth2array
2023-03-02 10:38:45 +01:00
2022-08-10 09:54:14 +02:00
$keyforsupportedoauth2array = getDolGlobalString ( $keyforsmtpoauthservice );
if ( preg_match ( '/^.*-/' , $keyforsupportedoauth2array )) {
$keyforprovider = preg_replace ( '/^.*-/' , '' , $keyforsupportedoauth2array );
} else {
$keyforprovider = '' ;
}
$keyforsupportedoauth2array = preg_replace ( '/-.*$/' , '' , $keyforsupportedoauth2array );
$keyforsupportedoauth2array = 'OAUTH_' . $keyforsupportedoauth2array . '_NAME' ;
$OAUTH_SERVICENAME = ( empty ( $supportedoauth2array [ $keyforsupportedoauth2array ][ 'name' ]) ? 'Unknown' : $supportedoauth2array [ $keyforsupportedoauth2array ][ 'name' ] . ( $keyforprovider ? '-' . $keyforprovider : '' ));
require_once DOL_DOCUMENT_ROOT . '/includes/OAuth/bootstrap.php' ;
2023-02-08 01:28:14 +01:00
$storage = new DoliStorage ( $db , $conf , $keyforprovider );
2022-08-11 10:03:44 +02:00
2022-08-10 09:54:14 +02:00
try {
2022-08-11 10:16:20 +02:00
$tokenobj = $storage -> retrieveAccessToken ( $OAUTH_SERVICENAME );
2022-08-11 10:03:44 +02:00
$expire = false ;
// Is token expired or will token expire in the next 30 seconds
if ( is_object ( $tokenobj )) {
$expire = ( $tokenobj -> getEndOfLife () !== - 9002 && $tokenobj -> getEndOfLife () !== - 9001 && time () > ( $tokenobj -> getEndOfLife () - 30 ));
}
// Token expired so we refresh it
2022-08-11 10:16:20 +02:00
if ( is_object ( $tokenobj ) && $expire ) {
$credentials = new Credentials (
2022-08-11 10:53:15 +02:00
getDolGlobalString ( 'OAUTH_' . getDolGlobalString ( 'MAIN_MAIL_SMTPS_OAUTH_SERVICE' ) . '_ID' ),
getDolGlobalString ( 'OAUTH_' . getDolGlobalString ( 'MAIN_MAIL_SMTPS_OAUTH_SERVICE' ) . '_SECRET' ),
getDolGlobalString ( 'OAUTH_' . getDolGlobalString ( 'MAIN_MAIL_SMTPS_OAUTH_SERVICE' ) . '_URLAUTHORIZE' )
2022-08-11 10:16:20 +02:00
);
$serviceFactory = new \OAuth\ServiceFactory ();
$oauthname = explode ( '-' , $OAUTH_SERVICENAME );
// ex service is Google-Emails we need only the first part Google
$apiService = $serviceFactory -> createService ( $oauthname [ 0 ], $credentials , $storage , array ());
2022-08-12 11:00:02 +02:00
// We have to save the token because Google give it only once
2022-08-11 10:16:20 +02:00
$refreshtoken = $tokenobj -> getRefreshToken ();
$tokenobj = $apiService -> refreshAccessToken ( $tokenobj );
$tokenobj -> setRefreshToken ( $refreshtoken );
$storage -> storeAccessToken ( $OAUTH_SERVICENAME , $tokenobj );
2022-08-11 10:03:44 +02:00
}
2022-08-10 09:54:14 +02:00
if ( is_object ( $tokenobj )) {
$this -> transport -> setAuthMode ( 'XOAUTH2' );
$this -> transport -> setPassword ( $tokenobj -> getAccessToken ());
} else {
$this -> errors [] = " Token not found " ;
}
} catch ( Exception $e ) {
// Return an error if token not found
$this -> errors [] = $e -> getMessage ();
2022-08-10 16:29:37 +02:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $e -> getMessage (), LOG_ERR );
2022-08-10 09:54:14 +02:00
}
}
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> $keyforsslseflsigned )) {
$this -> transport -> setStreamOptions ( array ( 'ssl' => array ( 'allow_self_signed' => true , 'verify_peer' => false )));
}
2017-04-18 01:39:06 +02:00
//$smtps->_msgReplyTo = 'reply@web.com';
2020-04-08 16:03:41 +02:00
// Switch content encoding to base64 - avoid the doubledot issue with quoted-printable
2020-09-07 10:18:17 +02:00
$contentEncoderBase64 = new Swift_Mime_ContentEncoder_Base64ContentEncoder ();
$this -> message -> setEncoder ( $contentEncoderBase64 );
2020-04-08 16:09:04 +02:00
2017-04-18 01:39:06 +02:00
// Create the Mailer using your created Transport
2018-01-21 15:55:56 +01:00
$this -> mailer = new Swift_Mailer ( $this -> transport );
2017-04-18 01:39:06 +02:00
2020-09-07 10:18:17 +02:00
// DKIM SIGN
if ( $conf -> global -> MAIN_MAIL_EMAIL_DKIM_ENABLED ) {
$privateKey = $conf -> global -> MAIN_MAIL_EMAIL_DKIM_PRIVATE_KEY ;
$domainName = $conf -> global -> MAIN_MAIL_EMAIL_DKIM_DOMAIN ;
$selector = $conf -> global -> MAIN_MAIL_EMAIL_DKIM_SELECTOR ;
$signer = new Swift_Signers_DKIMSigner ( $privateKey , $domainName , $selector );
$this -> message -> attachSigner ( $signer -> ignoreHeader ( 'Return-Path' ));
}
2018-01-25 22:03:51 +01:00
2020-09-07 10:18:17 +02:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_DEBUG )) {
2017-04-18 01:39:06 +02:00
// To use the ArrayLogger
$this -> logger = new Swift_Plugins_Loggers_ArrayLogger ();
// Or to use the Echo Logger
//$this->logger = new Swift_Plugins_Loggers_EchoLogger();
$this -> mailer -> registerPlugin ( new Swift_Plugins_LoggerPlugin ( $this -> logger ));
}
2023-02-16 02:59:29 +01:00
dol_syslog ( " CMailFile::sendfile: mailer->send, HOST= " . $server . " , PORT= " . $conf -> global -> $keyforsmtpport , LOG_DEBUG );
2017-04-18 01:39:06 +02:00
// send mail
2023-02-16 02:59:29 +01:00
$failedRecipients = array ();
2017-04-18 01:39:06 +02:00
try {
2021-05-18 17:57:23 +02:00
$result = $this -> mailer -> send ( $this -> message , $failedRecipients );
2017-04-18 01:39:06 +02:00
} catch ( Exception $e ) {
2022-08-10 10:09:52 +02:00
$this -> errors [] = $e -> getMessage ();
2017-04-18 01:39:06 +02:00
}
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_DEBUG )) {
$this -> dump_mail ();
}
2017-04-18 01:39:06 +02:00
$res = true ;
2022-08-10 10:09:52 +02:00
if ( ! empty ( $this -> error ) || ! empty ( $this -> errors ) || ! $result ) {
2021-05-18 17:57:23 +02:00
if ( ! empty ( $failedRecipients )) {
2022-08-10 10:09:52 +02:00
$this -> errors [] = 'Transport failed for the following addresses: "' . join ( '", "' , $failedRecipients ) . '".' ;
2021-05-18 17:57:23 +02:00
}
2017-04-18 01:39:06 +02:00
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_ERR );
2019-11-13 18:32:11 +01:00
$res = false ;
2023-03-02 10:38:45 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_DEBUG )) {
2023-03-30 14:48:04 +02:00
$this -> save_dump_mail_in_err ( 'Mail with topic ' . $this -> subject );
2023-03-02 10:38:45 +01:00
}
2020-05-21 15:05:19 +02:00
} else {
2018-10-29 03:25:21 +01:00
dol_syslog ( " CMailFile::sendfile: mail end success " , LOG_DEBUG );
}
2020-05-21 15:05:19 +02:00
} else {
2009-02-09 01:04:34 +01:00
// Send mail method not correctly defined
// --------------------------------------
2017-04-18 01:39:06 +02:00
return 'Bad value for sendmode' ;
2007-06-06 17:38:33 +02:00
}
2007-11-28 23:53:21 +01:00
2023-02-23 18:29:58 +01:00
// Now we delete image files that were created dynamically to manage data inline files
foreach ( $this -> html_images as $val ) {
if ( ! empty ( $val [ 'type' ]) && $val [ 'type' ] == 'cidfromdata' ) {
//dol_delete($val['fullpath']);
}
}
2022-12-20 17:38:01 +01:00
$parameters = array ( 'sent' => $res );
2021-03-01 20:37:16 +01:00
$action = '' ;
2018-02-03 17:32:38 +01:00
$reshook = $hookmanager -> executeHooks ( 'sendMailAfter' , $parameters , $this , $action ); // Note that $action and $object may have been modified by some hooks
2021-01-16 14:12:09 +01:00
if ( $reshook < 0 ) {
2019-11-13 18:32:11 +01:00
$this -> error = " Error in hook maildao sendMailAfter " . $reshook ;
dol_syslog ( " CMailFile::sendfile: mail end error= " . $this -> error , LOG_ERR );
2018-02-03 17:32:38 +01:00
return $reshook ;
}
2020-05-21 15:05:19 +02:00
} else {
2019-11-13 18:32:11 +01:00
$this -> error = 'No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS' ;
2010-07-15 01:12:49 +02:00
dol_syslog ( " CMailFile::sendfile: " . $this -> error , LOG_WARNING );
2006-04-01 03:10:38 +02:00
}
2005-06-25 15:02:39 +02:00
2019-11-13 18:32:11 +01:00
error_reporting ( $errorlevel ); // Reactive niveau erreur origine
2005-06-25 15:02:39 +02:00
2007-06-07 23:24:01 +02:00
return $res ;
}
2005-06-25 15:02:39 +02:00
2015-04-06 12:25:30 +02:00
/**
2015-04-06 20:02:29 +02:00
* Encode subject according to RFC 2822 - http :// en . wikipedia . org / wiki / MIME #Encoded-Word
2015-05-05 04:10:42 +02:00
*
2015-04-06 20:02:29 +02:00
* @ param string $stringtoencode String to encode
* @ return string string encoded
2015-04-06 12:25:30 +02:00
*/
2019-02-25 22:27:04 +01:00
public static function encodetorfc2822 ( $stringtoencode )
2009-05-13 16:49:30 +02:00
{
global $conf ;
return '=?' . $conf -> file -> character_set_client . '?B?' . base64_encode ( $stringtoencode ) . '?=' ;
}
2009-02-09 01:04:34 +01:00
2020-09-07 10:18:17 +02:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2009-02-09 01:04:34 +01:00
/**
2011-07-20 13:07:12 +02:00
* Read a file on disk and return encoded content for emails ( mode = 'mail' )
2010-01-13 00:03:34 +01:00
*
2011-12-01 23:36:00 +01:00
* @ param string $sourcefile Path to file to encode
2021-01-05 00:11:19 +01:00
* @ return int | string < 0 if KO , encoded string if OK
2009-02-09 01:04:34 +01:00
*/
2019-02-25 22:27:04 +01:00
private function _encode_file ( $sourcefile )
2009-02-09 01:04:34 +01:00
{
2020-09-07 10:18:17 +02:00
// phpcs:enable
2019-11-13 18:32:11 +01:00
$newsourcefile = dol_osencode ( $sourcefile );
2009-10-14 18:13:20 +02:00
2021-01-05 00:11:19 +01:00
if ( is_readable ( $newsourcefile )) {
2019-11-13 18:32:11 +01:00
$contents = file_get_contents ( $newsourcefile ); // Need PHP 4.3
$encoded = chunk_split ( base64_encode ( $contents ), 76 , $this -> eol ); // 76 max is defined into http://tools.ietf.org/html/rfc2047
2009-02-09 01:04:34 +01:00
return $encoded ;
2020-05-21 15:05:19 +02:00
} else {
2019-11-13 18:32:11 +01:00
$this -> error = " Error: Can't read file ' " . $sourcefile . " ' into _encode_file " ;
2009-02-20 23:53:15 +01:00
dol_syslog ( " CMailFile::encode_file: " . $this -> error , LOG_ERR );
2009-02-09 01:04:34 +01:00
return - 1 ;
}
}
2020-09-07 10:18:17 +02:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2008-11-15 01:52:42 +01:00
/**
2010-10-10 01:17:41 +02:00
* Write content of a SMTP request into a dump file ( mode = all )
* Used for debugging .
2013-03-13 19:14:49 +01:00
* Note that to see full SMTP protocol , you can use tcpdump - w / tmp / smtp - s 2000 port 25 "
2011-12-01 23:36:00 +01:00
*
* @ return void
2008-11-15 01:52:42 +01:00
*/
2019-02-25 22:27:04 +01:00
public function dump_mail ()
2008-11-15 01:52:42 +01:00
{
2020-09-07 10:18:17 +02:00
// phpcs:enable
2019-11-13 18:32:11 +01:00
global $conf , $dolibarr_main_data_root ;
2009-02-09 01:04:34 +01:00
2021-01-05 00:11:19 +01:00
if ( @ is_writeable ( $dolibarr_main_data_root )) { // Avoid fatal error on fopen with open_basedir
2019-11-13 18:32:11 +01:00
$outputfile = $dolibarr_main_data_root . " /dolibarr_mail.log " ;
2023-03-02 10:38:45 +01:00
$fp = fopen ( $outputfile , " w " ); // overwrite
2009-02-09 01:04:34 +01:00
2021-01-05 00:11:19 +01:00
if ( $this -> sendmode == 'mail' ) {
2009-02-09 01:04:34 +01:00
fputs ( $fp , $this -> headers );
2019-11-13 18:32:11 +01:00
fputs ( $fp , $this -> eol ); // This eol is added by the mail function, so we add it in log
2009-02-09 01:04:34 +01:00
fputs ( $fp , $this -> message );
2021-01-05 00:11:19 +01:00
} elseif ( $this -> sendmode == 'smtps' ) {
2019-11-13 18:32:11 +01:00
fputs ( $fp , $this -> smtps -> log ); // this->smtps->log is filled only if MAIN_MAIL_DEBUG was set to on
2021-01-05 00:11:19 +01:00
} elseif ( $this -> sendmode == 'swiftmailer' ) {
2019-11-13 18:32:11 +01:00
fputs ( $fp , $this -> logger -> dump ()); // this->logger is filled only if MAIN_MAIL_DEBUG was set to on
2017-04-18 01:39:06 +02:00
}
2009-02-09 01:04:34 +01:00
2008-11-15 01:52:42 +01:00
fclose ( $fp );
2023-02-17 19:30:50 +01:00
dolChmod ( $outputfile );
2008-11-15 01:52:42 +01:00
}
}
2023-03-02 10:38:45 +01:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Save content if mail is in error
* Used for debugging .
*
2023-03-30 14:48:04 +02:00
* @ param string $message Add also a message
2023-03-02 10:38:45 +01:00
* @ return void
*/
2023-03-30 14:48:04 +02:00
public function save_dump_mail_in_err ( $message = '' )
2023-03-02 10:38:45 +01:00
{
global $dolibarr_main_data_root ;
if ( @ is_writeable ( $dolibarr_main_data_root )) { // Avoid fatal error on fopen with open_basedir
2023-03-30 22:25:29 +02:00
$srcfile = $dolibarr_main_data_root . " /dolibarr_mail.log " ;
// Add message to dolibarr_mail.log. We do not use dol_syslog() on purpose,
// to be sure to write into dolibarr_mail.log
2023-03-30 14:48:04 +02:00
if ( $message ) {
2023-03-30 22:25:29 +02:00
// Test constant SYSLOG_FILE_NO_ERROR (should stay a constant defined with define('SYSLOG_FILE_NO_ERROR',1);
if ( defined ( 'SYSLOG_FILE_NO_ERROR' )) {
$filefd = @ fopen ( $srcfile , 'a+' );
} else {
$filefd = fopen ( $srcfile , 'a+' );
}
if ( $filefd ) {
fwrite ( $filefd , $message . " \n " );
fclose ( $filefd );
dolChmod ( $srcfile );
}
2023-03-30 14:48:04 +02:00
}
// Move dolibarr_mail.log into a dolibarr_mail.err or dolibarr_mail.date.err
2023-03-24 13:27:04 +01:00
if ( getDolGlobalString ( 'MAIN_MAIL_DEBUG_ERR_WITH_DATE' )) {
$destfile = $dolibarr_main_data_root . " /dolibarr_mail. " . dol_print_date ( dol_now (), 'dayhourlog' , 'gmt' ) . " .err " ;
} else {
$destfile = $dolibarr_main_data_root . " /dolibarr_mail.err " ;
}
2023-03-02 10:38:45 +01:00
2023-03-22 21:24:53 +01:00
require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php' ;
2023-03-02 10:38:45 +01:00
dol_move ( $srcfile , $destfile , 0 , 1 , 0 , 0 );
}
}
2010-10-10 01:17:41 +02:00
2017-04-18 01:39:06 +02:00
/**
* Correct an uncomplete html string
*
* @ param string $msg String
* @ return string Completed string
*/
2019-02-25 22:27:04 +01:00
public function checkIfHTML ( $msg )
2017-04-18 01:39:06 +02:00
{
2021-01-05 00:11:19 +01:00
if ( ! preg_match ( '/^[\s\t]*<html/i' , $msg )) {
2017-04-18 01:39:06 +02:00
$out = " <html><head><title></title> " ;
2021-01-16 14:12:09 +01:00
if ( ! empty ( $this -> styleCSS )) {
$out .= $this -> styleCSS ;
}
2019-11-13 18:32:11 +01:00
$out .= " </head><body " ;
2021-01-16 14:12:09 +01:00
if ( ! empty ( $this -> bodyCSS )) {
$out .= $this -> bodyCSS ;
}
2019-11-13 18:32:11 +01:00
$out .= " > " ;
$out .= $msg ;
$out .= " </body></html> " ;
2020-05-21 15:05:19 +02:00
} else {
2017-04-18 01:39:06 +02:00
$out = $msg ;
}
return $out ;
}
/**
* Build a css style ( mode = all ) into this -> styleCSS and this -> bodyCSS
*
2023-04-30 03:10:20 +02:00
* @ return void
2017-04-18 01:39:06 +02:00
*/
2019-02-25 22:27:04 +01:00
public function buildCSS ()
2017-04-18 01:39:06 +02:00
{
2021-01-05 00:11:19 +01:00
if ( ! empty ( $this -> css )) {
2017-04-18 01:39:06 +02:00
// Style CSS
$this -> styleCSS = '<style type="text/css">' ;
2019-11-13 18:32:11 +01:00
$this -> styleCSS .= 'body {' ;
2017-04-18 01:39:06 +02:00
2021-01-05 00:11:19 +01:00
if ( $this -> css [ 'bgcolor' ]) {
2019-11-13 18:32:11 +01:00
$this -> styleCSS .= ' background-color: ' . $this -> css [ 'bgcolor' ] . ';' ;
$this -> bodyCSS .= ' bgcolor="' . $this -> css [ 'bgcolor' ] . '"' ;
2017-04-18 01:39:06 +02:00
}
2021-01-05 00:11:19 +01:00
if ( $this -> css [ 'bgimage' ]) {
2017-04-18 01:39:06 +02:00
// TODO recuperer cid
2019-11-13 18:32:11 +01:00
$this -> styleCSS .= ' background-image: url("cid:' . $this -> css [ 'bgimage_cid' ] . '");' ;
2017-04-18 01:39:06 +02:00
}
2019-11-13 18:32:11 +01:00
$this -> styleCSS .= '}' ;
$this -> styleCSS .= '</style>' ;
2017-04-18 01:39:06 +02:00
}
}
2010-10-10 01:17:41 +02:00
2020-09-07 10:18:17 +02:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2008-11-15 01:52:42 +01:00
/**
2010-10-10 01:17:41 +02:00
* Create SMTP headers ( mode = 'mail' )
2010-01-13 00:03:34 +01:00
*
2015-04-06 12:25:30 +02:00
* @ return string headers
2008-11-15 01:52:42 +01:00
*/
2019-02-25 22:27:04 +01:00
public function write_smtpheaders ()
2008-11-15 01:52:42 +01:00
{
2020-09-07 10:18:17 +02:00
// phpcs:enable
2007-05-25 22:02:23 +02:00
global $conf ;
$out = " " ;
2006-08-06 20:34:37 +02:00
2016-12-15 12:11:39 +01:00
$host = dol_getprefix ( 'email' );
2012-02-01 22:39:17 +01:00
2006-08-06 20:34:37 +02:00
// Sender
2012-02-10 13:28:53 +01:00
//$out.= "Sender: ".getValidAddress($this->addr_from,2)).$this->eol2;
2019-11-13 18:32:11 +01:00
$out .= " From: " . $this -> getValidAddress ( $this -> addr_from , 3 , 1 ) . $this -> eol2 ;
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_MAIL_SENDMAIL_FORCE_BA )) {
2019-11-13 18:32:11 +01:00
$out .= " To: " . $this -> getValidAddress ( $this -> addr_to , 0 , 1 ) . $this -> eol2 ;
2012-11-13 17:25:47 +01:00
}
2014-06-28 14:06:29 +02:00
// 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.
2019-11-13 18:32:11 +01:00
$out .= " Return-Path: " . $this -> getValidAddress ( $this -> addr_from , 0 , 1 ) . $this -> eol2 ;
2021-01-16 14:12:09 +01:00
if ( isset ( $this -> reply_to ) && $this -> reply_to ) {
$out .= " Reply-To: " . $this -> getValidAddress ( $this -> reply_to , 2 ) . $this -> eol2 ;
}
if ( isset ( $this -> errors_to ) && $this -> errors_to ) {
$out .= " Errors-To: " . $this -> getValidAddress ( $this -> errors_to , 2 ) . $this -> eol2 ;
}
2006-08-06 20:34:37 +02:00
// Receiver
2021-01-16 14:12:09 +01:00
if ( isset ( $this -> addr_cc ) && $this -> addr_cc ) {
$out .= " Cc: " . $this -> getValidAddress ( $this -> addr_cc , 2 ) . $this -> eol2 ;
}
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 ?
}
2008-11-15 01:52:42 +01:00
2012-02-04 13:39:21 +01:00
// Delivery receipt
2021-01-16 14:12:09 +01:00
if ( isset ( $this -> deliveryreceipt ) && $this -> deliveryreceipt == 1 ) {
$out .= " Disposition-Notification-To: " . $this -> getValidAddress ( $this -> addr_from , 2 ) . $this -> eol2 ;
}
2008-11-15 01:52:42 +01:00
2012-02-08 12:55:25 +01:00
//$out.= "X-Priority: 3".$this->eol2;
2012-02-01 22:39:17 +01:00
2019-11-13 18:32:11 +01:00
$out .= 'Date: ' . date ( " r " ) . $this -> eol2 ;
2015-05-05 04:10:42 +02:00
$trackid = $this -> trackid ;
2021-01-16 14:12:09 +01:00
if ( $trackid ) {
2015-11-13 00:19:11 +01:00
// References is kept in response and Message-ID is returned into In-Reply-To:
2019-11-14 10:01:05 +01:00
$this -> msgid = time () . '.phpmail-dolibarr-' . $trackid . '@' . $host ;
$out .= 'Message-ID: <' . $this -> msgid . " > " . $this -> eol2 ; // Uppercase seems replaced by phpmail
$out .= 'References: <' . $this -> msgid . " > " . $this -> eol2 ;
2019-11-13 18:32:11 +01:00
$out .= 'X-Dolibarr-TRACKID: ' . $trackid . '@' . $host . $this -> eol2 ;
2020-05-21 15:05:19 +02:00
} else {
2019-11-14 10:01:05 +01:00
$this -> msgid = time () . '.phpmail@' . $host ;
$out .= 'Message-ID: <' . $this -> msgid . " > " . $this -> eol2 ;
2015-05-05 04:10:42 +02:00
}
2012-02-01 22:39:17 +01:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $_SERVER [ 'REMOTE_ADDR' ])) {
$out .= " X-RemoteAddr: " . $_SERVER [ 'REMOTE_ADDR' ] . $this -> eol2 ;
}
2019-11-13 18:32:11 +01:00
$out .= " X-Mailer: Dolibarr version " . DOL_VERSION . " (using php mail) " . $this -> eol2 ;
$out .= " Mime-Version: 1.0 " . $this -> eol2 ;
2006-08-06 20:34:37 +02:00
2012-02-05 01:11:20 +01:00
//$out.= "From: ".$this->getValidAddress($this->addr_from,3,1).$this->eol;
2012-02-04 13:39:21 +01:00
2019-11-13 18:32:11 +01:00
$out .= " Content-Type: multipart/mixed; " . $this -> eol2 . " boundary= \" " . $this -> mixed_boundary . " \" " . $this -> eol2 ;
$out .= " Content-Transfer-Encoding: 8bit " . $this -> eol2 ; // TODO Seems to be ignored. Header is 7bit once received.
2017-04-18 01:39:06 +02:00
2009-05-18 00:54:12 +02:00
dol_syslog ( " CMailFile::write_smtpheaders smtp_header= \n " . $out );
2008-11-15 01:52:42 +01:00
return $out ;
}
2006-08-06 20:34:37 +02:00
2020-09-07 10:18:17 +02:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2008-11-15 01:52:42 +01:00
/**
2011-07-20 13:07:12 +02:00
* Create header MIME ( mode = 'mail' )
2010-01-13 00:03:34 +01:00
*
2011-12-07 17:28:11 +01:00
* @ param array $filename_list Array of filenames
* @ param array $mimefilename_list Array of mime types
2015-04-06 12:25:30 +02:00
* @ return string mime headers
2008-11-15 01:52:42 +01:00
*/
2019-02-25 22:27:04 +01:00
public function write_mimeheaders ( $filename_list , $mimefilename_list )
2008-11-15 01:52:42 +01:00
{
2020-09-07 10:18:17 +02:00
// phpcs:enable
2019-11-13 18:32:11 +01:00
$mimedone = 0 ;
2008-11-15 01:52:42 +01:00
$out = " " ;
2009-05-13 16:49:30 +02:00
2021-01-16 14:12:09 +01:00
if ( is_array ( $filename_list )) {
2019-11-13 18:32:11 +01:00
$filename_list_size = count ( $filename_list );
2021-01-16 14:12:09 +01:00
for ( $i = 0 ; $i < $filename_list_size ; $i ++ ) {
if ( $filename_list [ $i ]) {
if ( $mimefilename_list [ $i ]) {
$filename_list [ $i ] = $mimefilename_list [ $i ];
}
2019-11-13 18:32:11 +01:00
$out .= " X-attachments: $filename_list[$i] " . $this -> eol2 ;
2006-08-06 20:34:37 +02:00
}
2008-11-15 01:52:42 +01:00
}
}
2009-05-13 16:49:30 +02:00
2009-02-20 23:53:15 +01:00
dol_syslog ( " CMailFile::write_mimeheaders mime_header= \n " . $out , LOG_DEBUG );
2008-11-15 01:52:42 +01:00
return $out ;
}
2020-09-07 10:18:17 +02:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2008-11-15 01:52:42 +01:00
/**
2011-07-20 13:07:12 +02:00
* Return email content ( mode = 'mail' )
2010-01-13 00:03:34 +01:00
*
2011-12-07 17:28:11 +01:00
* @ param string $msgtext Message string
* @ return string String content
2008-11-15 01:52:42 +01:00
*/
2019-02-25 22:27:04 +01:00
public function write_body ( $msgtext )
2008-11-15 01:52:42 +01:00
{
2020-09-07 10:18:17 +02:00
// phpcs:enable
2008-11-15 01:52:42 +01:00
global $conf ;
2019-11-13 18:32:11 +01:00
$out = '' ;
2011-07-02 18:48:31 +02:00
2019-11-13 18:32:11 +01:00
$out .= " -- " . $this -> mixed_boundary . $this -> eol ;
2012-06-17 18:40:45 +02:00
2021-01-16 14:12:09 +01:00
if ( $this -> atleastoneimage ) {
2019-11-13 18:32:11 +01:00
$out .= " Content-Type: multipart/alternative; " . $this -> eol . " boundary= \" " . $this -> alternative_boundary . " \" " . $this -> eol ;
$out .= $this -> eol ;
$out .= " -- " . $this -> alternative_boundary . $this -> eol ;
2009-05-13 16:49:30 +02:00
}
2011-07-02 18:48:31 +02:00
2009-05-13 21:10:06 +02:00
// Make RFC821 Compliant, replace bare linefeeds
2019-11-13 18:32:11 +01:00
$strContent = preg_replace ( " /(?<! \r ) \n /si " , " \r \n " , $msgtext ); // PCRE modifier /s means new lines are common chars
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> MAIN_FIX_FOR_BUGGED_MTA )) {
2019-11-13 18:32:11 +01:00
$strContent = preg_replace ( " / \r \n /si " , " \n " , $strContent ); // PCRE modifier /s means new lines are common chars
2012-11-13 17:25:47 +01:00
}
2013-03-13 19:14:49 +01:00
2017-04-05 01:01:43 +02:00
$strContentAltText = '' ;
2021-01-16 14:12:09 +01:00
if ( $this -> msgishtml ) {
2019-11-06 00:27:36 +01:00
// Similar code to forge a text from html is also in smtps.class.php
2019-11-06 00:51:26 +01:00
$strContentAltText = preg_replace ( " /<br \ s*[^>]*>/ " , " " , $strContent );
2022-10-23 17:14:23 +02:00
// TODO We could replace <img ...> with [Filename.ext] like Gmail do.
$strContentAltText = html_entity_decode ( strip_tags ( $strContentAltText )); // Remove any HTML tags
2019-11-13 18:32:11 +01:00
$strContentAltText = trim ( wordwrap ( $strContentAltText , 75 , empty ( $conf -> global -> MAIN_FIX_FOR_BUGGED_MTA ) ? " \r \n " : " \n " ));
2017-04-18 01:39:06 +02:00
// Check if html header already in message, if not complete the message
2017-04-05 01:01:43 +02:00
$strContent = $this -> checkIfHTML ( $strContent );
}
2016-12-19 01:04:17 +01:00
// Make RFC2045 Compliant, split lines
2017-04-18 01:39:06 +02:00
//$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content
2017-10-16 14:31:28 +02:00
// TODO Encode main content into base64 and use the chunk_split, or quoted-printable
2019-11-13 18:32:11 +01:00
$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.
2009-05-13 21:10:06 +02:00
2021-01-16 14:12:09 +01:00
if ( $this -> msgishtml ) {
if ( $this -> atleastoneimage ) {
2019-11-13 18:32:11 +01:00
$out .= " Content-Type: text/plain; charset= " . $conf -> file -> character_set_client . $this -> eol ;
2017-10-16 14:31:28 +02:00
//$out.= "Content-Transfer-Encoding: 7bit".$this->eol;
2019-11-13 18:32:11 +01:00
$out .= $this -> eol . ( $strContentAltText ? $strContentAltText : strip_tags ( $strContent )) . $this -> eol ; // Add plain text message
$out .= " -- " . $this -> alternative_boundary . $this -> eol ;
$out .= " Content-Type: multipart/related; " . $this -> eol . " boundary= \" " . $this -> related_boundary . " \" " . $this -> eol ;
$out .= $this -> eol ;
$out .= " -- " . $this -> related_boundary . $this -> eol ;
2011-06-20 23:18:06 +02:00
}
2017-08-24 02:02:00 +02:00
2021-01-16 14:12:09 +01:00
if ( ! $this -> atleastoneimage && $strContentAltText && ! empty ( $conf -> global -> MAIN_MAIL_USE_MULTI_PART )) { // Add plain text message part before html part
2019-11-13 18:32:11 +01:00
$out .= " Content-Type: multipart/alternative; " . $this -> eol . " boundary= \" " . $this -> alternative_boundary . " \" " . $this -> eol ;
$out .= $this -> eol ;
$out .= " -- " . $this -> alternative_boundary . $this -> eol ;
$out .= " Content-Type: text/plain; charset= " . $conf -> file -> character_set_client . $this -> eol ;
2017-10-16 14:31:28 +02:00
//$out.= "Content-Transfer-Encoding: 7bit".$this->eol;
2019-11-13 18:32:11 +01:00
$out .= $this -> eol . $strContentAltText . $this -> eol ;
$out .= " -- " . $this -> alternative_boundary . $this -> eol ;
2017-04-05 01:01:43 +02:00
}
2017-08-24 02:02:00 +02:00
2019-11-13 18:32:11 +01:00
$out .= " Content-Type: text/html; charset= " . $conf -> file -> character_set_client . $this -> eol ;
2017-10-16 14:31:28 +02:00
//$out.= "Content-Transfer-Encoding: 7bit".$this->eol; // TODO Use base64
2019-11-13 18:32:11 +01:00
$out .= $this -> eol . $strContent . $this -> eol ;
2017-04-18 01:39:06 +02:00
2021-01-16 14:12:09 +01:00
if ( ! $this -> atleastoneimage && $strContentAltText && ! empty ( $conf -> global -> MAIN_MAIL_USE_MULTI_PART )) { // Add plain text message part after html part
2019-11-13 18:32:11 +01:00
$out .= " -- " . $this -> alternative_boundary . " -- " . $this -> eol ;
2017-04-05 01:01:43 +02:00
}
2020-05-21 15:05:19 +02:00
} else {
2019-11-13 18:32:11 +01:00
$out .= " Content-Type: text/plain; charset= " . $conf -> file -> character_set_client . $this -> eol ;
2017-10-16 14:31:28 +02:00
//$out.= "Content-Transfer-Encoding: 7bit".$this->eol;
2019-11-13 18:32:11 +01:00
$out .= $this -> eol . $strContent . $this -> eol ;
2011-06-20 23:18:06 +02:00
}
2011-07-02 18:48:31 +02:00
2019-11-13 18:32:11 +01:00
$out .= $this -> eol ;
2009-05-13 21:10:06 +02:00
2017-04-05 01:01:43 +02:00
// Encode images
2021-01-16 14:12:09 +01:00
if ( $this -> atleastoneimage ) {
2017-04-18 01:39:06 +02:00
$out .= $this -> write_images ( $this -> images_encoded );
// always end related and end alternative after inline images
2019-11-13 18:32:11 +01:00
$out .= " -- " . $this -> related_boundary . " -- " . $this -> eol ;
$out .= $this -> eol . " -- " . $this -> alternative_boundary . " -- " . $this -> eol ;
2017-04-18 01:39:06 +02:00
$out .= $this -> eol ;
2017-04-05 01:01:43 +02:00
}
2017-04-18 01:39:06 +02:00
2008-11-15 01:52:42 +01:00
return $out ;
}
2009-05-13 16:49:30 +02:00
2020-09-07 10:18:17 +02:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2008-11-15 01:52:42 +01:00
/**
2011-07-20 13:07:12 +02:00
* Attach file to email ( mode = 'mail' )
2010-01-13 00:03:34 +01:00
*
2011-12-07 17:28:11 +01:00
* @ param array $filename_list Tableau
* @ param array $mimetype_list Tableau
* @ param array $mimefilename_list Tableau
2022-10-23 17:14:23 +02:00
* @ param array $cidlist Array of CID if file must be completed with CID code
* @ return string String with files encoded
2008-11-15 01:52:42 +01:00
*/
2022-10-23 17:14:23 +02:00
private function write_files ( $filename_list , $mimetype_list , $mimefilename_list , $cidlist )
2008-11-15 01:52:42 +01:00
{
2020-09-07 10:18:17 +02:00
// phpcs:enable
2008-11-15 01:52:42 +01:00
$out = '' ;
2019-11-13 18:32:11 +01:00
$filename_list_size = count ( $filename_list );
2021-01-16 14:12:09 +01:00
for ( $i = 0 ; $i < $filename_list_size ; $i ++ ) {
if ( $filename_list [ $i ]) {
2009-02-20 23:53:15 +01:00
dol_syslog ( " CMailFile::write_files: i= $i " );
2008-11-15 01:52:42 +01:00
$encoded = $this -> _encode_file ( $filename_list [ $i ]);
2021-01-16 14:12:09 +01:00
if ( $encoded >= 0 ) {
if ( $mimefilename_list [ $i ]) {
$filename_list [ $i ] = $mimefilename_list [ $i ];
}
2019-11-13 18:32:11 +01:00
if ( ! $mimetype_list [ $i ]) {
2017-04-18 01:39:06 +02:00
$mimetype_list [ $i ] = " application/octet-stream " ;
}
2008-11-15 01:52:42 +01:00
2019-11-13 18:32:11 +01:00
$out .= " -- " . $this -> mixed_boundary . $this -> eol ;
$out .= " Content-Disposition: attachment; filename= \" " . $filename_list [ $i ] . " \" " . $this -> eol ;
$out .= " Content-Type: " . $mimetype_list [ $i ] . " ; name= \" " . $filename_list [ $i ] . " \" " . $this -> eol ;
$out .= " Content-Transfer-Encoding: base64 " . $this -> eol ;
$out .= " Content-Description: " . $filename_list [ $i ] . $this -> eol ;
2022-10-23 17:14:23 +02:00
if ( ! empty ( $cidlist ) && is_array ( $cidlist ) && $cidlist [ $i ]) {
$out .= " X-Attachment-Id: " . $cidlist [ $i ] . $this -> eol ;
$out .= " Content-ID: < " . $cidlist [ $i ] . '>' . $this -> eol ;
}
2019-11-13 18:32:11 +01:00
$out .= $this -> eol ;
$out .= $encoded ;
$out .= $this -> eol ;
2009-05-11 19:13:56 +02:00
//$out.= $this->eol;
2020-05-21 15:05:19 +02:00
} else {
2008-11-15 01:52:42 +01:00
return $encoded ;
}
2006-08-06 20:34:37 +02:00
}
2008-11-15 01:52:42 +01:00
}
2005-06-25 15:02:39 +02:00
2009-05-13 21:10:06 +02:00
return $out ;
}
2020-09-07 10:18:17 +02:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2009-05-13 21:10:06 +02:00
/**
2011-07-20 13:07:12 +02:00
* Attach an image to email ( mode = 'mail' )
2010-01-13 00:03:34 +01:00
*
2018-09-16 10:09:19 +02:00
* @ param array $images_list Array of array image
2011-12-07 17:28:11 +01:00
* @ return string Chaine images encodees
2009-05-13 21:10:06 +02:00
*/
2019-02-25 22:27:04 +01:00
public function write_images ( $images_list )
2009-05-13 21:10:06 +02:00
{
2020-09-07 10:18:17 +02:00
// phpcs:enable
2009-05-13 21:10:06 +02:00
$out = '' ;
2021-01-16 14:12:09 +01:00
if ( is_array ( $images_list )) {
foreach ( $images_list as $img ) {
2018-11-19 23:43:58 +01:00
dol_syslog ( " CMailFile::write_images: " . $img [ " name " ]);
2009-05-13 21:10:06 +02:00
2019-11-13 18:32:11 +01:00
$out .= " -- " . $this -> related_boundary . $this -> eol ; // always related for an inline image
$out .= " Content-Type: " . $img [ " content_type " ] . " ; name= \" " . $img [ " name " ] . " \" " . $this -> eol ;
$out .= " Content-Transfer-Encoding: base64 " . $this -> eol ;
$out .= " Content-Disposition: inline; filename= \" " . $img [ " name " ] . " \" " . $this -> eol ;
$out .= " Content-ID: < " . $img [ " cid " ] . " > " . $this -> eol ;
$out .= $this -> eol ;
$out .= $img [ " image_encoded " ];
$out .= $this -> eol ;
2009-05-13 21:10:06 +02:00
}
}
2009-05-11 19:13:56 +02:00
2008-11-15 01:52:42 +01:00
return $out ;
}
2020-09-07 10:18:17 +02:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2009-11-01 15:16:30 +01:00
/**
* Try to create a socket connection
2011-07-20 13:07:12 +02:00
*
2011-12-07 17:28:11 +01:00
* @ param string $host Add ssl :// for SSL / TLS .
* @ param int $port Example : 25 , 465
* @ return int Socket id if ok , 0 if KO
2009-11-01 15:16:30 +01:00
*/
2019-02-25 22:27:04 +01:00
public function check_server_port ( $host , $port )
2008-04-17 01:11:45 +02:00
{
2020-09-07 10:18:17 +02:00
// phpcs:enable
2017-04-18 01:39:06 +02:00
global $conf ;
2017-08-24 02:02:00 +02:00
2019-11-13 18:32:11 +01:00
$_retVal = 0 ;
$timeout = 5 ; // Timeout in seconds
2008-04-17 01:11:45 +02:00
2021-01-16 14:12:09 +01:00
if ( function_exists ( 'fsockopen' )) {
2019-11-13 18:32:11 +01:00
$keyforsmtpserver = 'MAIN_MAIL_SMTP_SERVER' ;
$keyforsmtpport = 'MAIN_MAIL_SMTP_PORT' ;
$keyforsmtpid = 'MAIN_MAIL_SMTPS_ID' ;
$keyforsmtppw = 'MAIN_MAIL_SMTPS_PW' ;
2022-08-31 14:02:09 +02:00
$keyforsmtpauthtype = 'MAIN_MAIL_SMTPS_AUTH_TYPE' ;
$keyforsmtpoauthservice = 'MAIN_MAIL_SMTPS_OAUTH_SERVICE' ;
2019-11-13 18:32:11 +01:00
$keyfortls = 'MAIN_MAIL_EMAIL_TLS' ;
$keyforstarttls = 'MAIN_MAIL_EMAIL_STARTTLS' ;
2022-08-31 14:02:09 +02:00
$keyforsslseflsigned = 'MAIN_MAIL_EMAIL_SMTP_ALLOW_SELF_SIGNED' ;
if ( ! empty ( $this -> sendcontext )) {
$smtpContextKey = strtoupper ( $this -> sendcontext );
$smtpContextSendMode = getDolGlobalString ( 'MAIN_MAIL_SENDMODE_' . $smtpContextKey );
if ( ! empty ( $smtpContextSendMode ) && $smtpContextSendMode != 'default' ) {
$keyforsmtpserver = 'MAIN_MAIL_SMTP_SERVER_' . $smtpContextKey ;
$keyforsmtpport = 'MAIN_MAIL_SMTP_PORT_' . $smtpContextKey ;
$keyforsmtpid = 'MAIN_MAIL_SMTPS_ID_' . $smtpContextKey ;
$keyforsmtppw = 'MAIN_MAIL_SMTPS_PW_' . $smtpContextKey ;
$keyforsmtpauthtype = 'MAIN_MAIL_SMTPS_AUTH_TYPE_' . $smtpContextKey ;
$keyforsmtpoauthservice = 'MAIN_MAIL_SMTPS_OAUTH_SERVICE_' . $smtpContextKey ;
$keyfortls = 'MAIN_MAIL_EMAIL_TLS_' . $smtpContextKey ;
$keyforstarttls = 'MAIN_MAIL_EMAIL_STARTTLS_' . $smtpContextKey ;
$keyforsslseflsigned = 'MAIN_MAIL_EMAIL_SMTP_ALLOW_SELF_SIGNED_' . $smtpContextKey ;
}
2017-08-24 02:02:00 +02:00
}
2017-04-18 01:39:06 +02:00
// If we use SSL/TLS
2021-01-16 14:12:09 +01:00
if ( ! empty ( $conf -> global -> $keyfortls ) && function_exists ( 'openssl_open' )) {
$host = 'ssl://' . $host ;
}
2017-04-18 01:39:06 +02:00
// tls smtp start with no encryption
2022-08-31 22:14:20 +02:00
//if (!empty($conf->global->MAIN_MAIL_EMAIL_STARTTLS) && function_exists('openssl_open')) $host='tls://'.$host;
2016-04-18 00:47:08 +02:00
2009-10-28 21:37:06 +01:00
dol_syslog ( " Try socket connection to host= " . $host . " port= " . $port );
2008-04-17 01:11:45 +02:00
//See if we can connect to the SMTP server
2022-08-24 10:22:48 +02:00
$errno = 0 ; $errstr = '' ;
2020-09-07 10:18:17 +02:00
if ( $socket = @ fsockopen (
2021-01-16 14:12:09 +01:00
$host , // Host to test, IP or domain. Add ssl:// for SSL/TLS.
$port , // which Port number to use
$errno , // actual system level error
$errstr , // and any text that goes with the error
$timeout // timeout for reading/writing data over the socket
2019-02-10 10:45:49 +01:00
)) {
2008-04-17 01:11:45 +02:00
// Windows still does not have support for this timeout function
2021-01-16 14:12:09 +01:00
if ( function_exists ( 'stream_set_timeout' )) {
stream_set_timeout ( $socket , $timeout , 0 );
}
2009-10-28 21:37:06 +01:00
dol_syslog ( " Now we wait for answer 220 " );
2008-04-17 01:11:45 +02:00
// Check response from Server
2021-01-16 14:12:09 +01:00
if ( $_retVal = $this -> server_parse ( $socket , " 220 " )) {
$_retVal = $socket ;
}
2020-05-21 15:05:19 +02:00
} else {
2019-11-13 18:32:11 +01:00
$this -> error = utf8_check ( 'Error ' . $errno . ' - ' . $errstr ) ? 'Error ' . $errno . ' - ' . $errstr : utf8_encode ( 'Error ' . $errno . ' - ' . $errstr );
2008-04-17 01:11:45 +02:00
}
}
return $_retVal ;
}
2020-09-07 10:18:17 +02:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2010-07-21 19:39:17 +02:00
/**
2011-07-20 13:07:12 +02:00
* This function has been modified as provided by SirSir to allow multiline responses when
2010-07-21 19:39:17 +02:00
* using SMTP Extensions .
2011-07-20 13:07:12 +02:00
*
2019-04-04 18:33:12 +02:00
* @ param resource $socket Socket
* @ param string $response Response string
* @ return boolean true if success
2010-07-21 19:39:17 +02:00
*/
2019-02-25 22:27:04 +01:00
public function server_parse ( $socket , $response )
2008-04-17 01:11:45 +02:00
{
2020-09-07 10:18:17 +02:00
// phpcs:enable
2019-11-13 18:32:11 +01:00
$_retVal = true ; // Indicates if Object was created or not
2008-04-17 01:11:45 +02:00
$server_response = '' ;
2021-01-16 14:12:09 +01:00
while ( substr ( $server_response , 3 , 1 ) != ' ' ) {
if ( ! ( $server_response = fgets ( $socket , 256 ))) {
2019-11-13 18:32:11 +01:00
$this -> error = " Couldn't get mail server response codes " ;
2016-10-01 16:41:12 +02:00
return false ;
2008-04-17 01:11:45 +02:00
}
}
2021-01-16 14:12:09 +01:00
if ( ! ( substr ( $server_response , 0 , 3 ) == $response )) {
2019-11-13 18:32:11 +01:00
$this -> error = " Ran into problems sending Mail. \r \n Response: $server_response " ;
2008-04-17 01:11:45 +02:00
$_retVal = false ;
}
return $_retVal ;
2008-11-15 01:52:42 +01:00
}
2009-05-13 16:49:30 +02:00
2009-05-11 19:13:56 +02:00
/**
2023-02-23 18:29:58 +01:00
* Search images into html message and init array this -> images_encoded if found
2010-01-13 00:03:34 +01:00
*
2022-10-23 17:14:23 +02:00
* @ param string $images_dir Location of physical images files . For example $dolibarr_main_data_root . '/medias'
2011-12-07 17:28:11 +01:00
* @ return int > 0 if OK , < 0 if KO
2009-05-11 19:13:56 +02:00
*/
2022-10-23 17:14:23 +02:00
private function findHtmlImages ( $images_dir )
2009-05-13 16:49:30 +02:00
{
2022-10-23 17:14:23 +02:00
// Build the array of image extensions
2009-05-13 16:49:30 +02:00
$extensions = array_keys ( $this -> image_types );
2022-10-23 17:14:23 +02:00
// We search (into mail body this->html), if we find some strings like "... file=xxx.img"
// For example when:
// <img alt="" src="/viewimage.php?modulepart=medias&entity=1&file=image/picture.jpg" style="height:356px; width:1040px" />
2018-10-19 15:02:54 +02:00
$matches = array ();
2019-11-13 18:32:11 +01:00
preg_match_all ( '/(?:"|\')([^"\']+\.(' . implode ( '|' , $extensions ) . '))(?:"|\')/Ui' , $this -> html , $matches ); // If "xxx.ext" or 'xxx.ext' found
2009-05-13 16:49:30 +02:00
2021-01-16 14:12:09 +01:00
if ( ! empty ( $matches )) {
2019-11-13 18:32:11 +01:00
$i = 0 ;
2022-10-23 17:14:23 +02:00
// We are interested in $matches[1] only (the second set of parenthesis into regex)
2021-01-16 14:12:09 +01:00
foreach ( $matches [ 1 ] as $full ) {
2022-10-23 17:14:23 +02:00
$regs = array ();
2021-01-16 14:12:09 +01:00
if ( preg_match ( '/file=([A-Za-z0-9_\-\/]+[\.]?[A-Za-z0-9]+)?$/i' , $full , $regs )) { // If xxx is 'file=aaa'
2009-11-18 15:19:03 +01:00
$img = $regs [ 1 ];
2010-01-13 00:03:34 +01:00
2021-01-16 14:12:09 +01:00
if ( file_exists ( $images_dir . '/' . $img )) {
2009-11-18 15:19:03 +01:00
// Image path in src
2019-01-27 11:55:16 +01:00
$src = preg_quote ( $full , '/' );
2009-11-18 15:19:03 +01:00
// Image full path
$this -> html_images [ $i ][ " fullpath " ] = $images_dir . '/' . $img ;
// Image name
$this -> html_images [ $i ][ " name " ] = $img ;
// Content type
2022-10-23 17:14:23 +02:00
$regext = array ();
if ( preg_match ( '/^.+\.(\w{3,4})$/' , $img , $regext )) {
$ext = strtolower ( $regext [ 1 ]);
2013-09-11 15:17:31 +02:00
$this -> html_images [ $i ][ " content_type " ] = $this -> image_types [ $ext ];
2013-09-11 14:48:02 +02:00
}
2009-11-18 15:19:03 +01:00
// cid
2023-02-25 04:05:18 +01:00
$this -> html_images [ $i ][ " cid " ] = dol_hash ( $this -> html_images [ $i ][ " fullpath " ], 'md5' ); // Force md5 hash (does not contains special chars)
2022-10-23 17:14:23 +02:00
// type
$this -> html_images [ $i ][ " type " ] = 'cidfromurl' ;
2009-11-18 15:19:03 +01:00
$this -> html = preg_replace ( " /src= \" $src\ " | src = '$src' / i " , " src = \ " cid: " . $this -> html_images [ $i ][ " cid " ] . " \" " , $this -> html );
}
$i ++ ;
2009-05-13 16:49:30 +02:00
}
}
2021-01-16 14:12:09 +01:00
if ( ! empty ( $this -> html_images )) {
2009-05-18 09:30:53 +02:00
$inline = array ();
2019-11-13 18:32:11 +01:00
$i = 0 ;
2009-05-13 16:49:30 +02:00
2021-01-16 14:12:09 +01:00
foreach ( $this -> html_images as $img ) {
2009-05-18 09:30:53 +02:00
$fullpath = $images_dir . '/' . $img [ " name " ];
2009-05-24 22:01:25 +02:00
2009-05-18 09:30:53 +02:00
// If duplicate images are embedded, they may show up as attachments, so remove them.
2021-01-16 14:12:09 +01:00
if ( ! in_array ( $fullpath , $inline )) {
2009-05-18 09:30:53 +02:00
// Read image file
2021-01-16 14:12:09 +01:00
if ( $image = file_get_contents ( $fullpath )) {
2009-05-18 09:30:53 +02:00
// On garde que le nom de l'image
2022-10-23 17:14:23 +02:00
$regs = array ();
2019-01-27 11:55:16 +01:00
preg_match ( '/([A-Za-z0-9_-]+[\.]?[A-Za-z0-9]+)?$/i' , $img [ " name " ], $regs );
2009-05-18 09:30:53 +02:00
$imgName = $regs [ 1 ];
2009-05-24 22:01:25 +02:00
2009-05-18 09:30:53 +02:00
$this -> images_encoded [ $i ][ 'name' ] = $imgName ;
2016-04-17 10:28:21 +02:00
$this -> images_encoded [ $i ][ 'fullpath' ] = $fullpath ;
2009-05-18 09:30:53 +02:00
$this -> images_encoded [ $i ][ 'content_type' ] = $img [ " content_type " ];
$this -> images_encoded [ $i ][ 'cid' ] = $img [ " cid " ];
// Encodage de l'image
$this -> images_encoded [ $i ][ " image_encoded " ] = chunk_split ( base64_encode ( $image ), 68 , $this -> eol );
$inline [] = $fullpath ;
}
2009-05-13 16:49:30 +02:00
}
$i ++ ;
}
2020-05-21 15:05:19 +02:00
} else {
2009-05-13 16:49:30 +02:00
return - 1 ;
}
return 1 ;
2020-05-21 15:05:19 +02:00
} else {
2009-05-13 16:49:30 +02:00
return 0 ;
}
}
2009-05-18 00:54:12 +02:00
2022-10-23 17:14:23 +02:00
/**
2023-02-23 18:29:58 +01:00
* Seearch images with data : image format into html message .
* If we find some , we create it on disk .
2022-10-23 17:14:23 +02:00
*
* @ param string $images_dir Location of where to store physicaly images files . For example $dolibarr_main_data_root . '/medias'
* @ return int > 0 if OK , < 0 if KO
*/
private function findHtmlImagesIsSrcData ( $images_dir )
{
global $conf ;
// Build the array of image extensions
$extensions = array_keys ( $this -> image_types );
if ( $images_dir && ! dol_is_dir ( $images_dir )) {
dol_mkdir ( $images_dir , DOL_DATA_ROOT );
}
// Uncomment this for debug
/*
global $dolibarr_main_data_root ;
$outputfile = $dolibarr_main_data_root . " /dolibarr_mail.log " ;
2022-10-28 04:20:54 +02:00
$fp = fopen ( $outputfile , " w+ " );
2022-10-23 17:14:23 +02:00
fwrite ( $fp , $this -> html );
fclose ( $fp );
*/
// We search (into mail body this->html), if we find some strings like "... file=xxx.img"
// For example when:
// <img alt="" src="/viewimage.php?modulepart=medias&entity=1&file=image/picture.jpg" style="height:356px; width:1040px" />
$matches = array ();
preg_match_all ( '/src="data:image\/(' . implode ( '|' , $extensions ) . ');base64,([^"]+)"/Ui' , $this -> html , $matches ); // If "xxx.ext" or 'xxx.ext' found
2022-10-23 22:32:52 +02:00
if ( ! empty ( $matches ) && ! empty ( $matches [ 1 ])) {
2022-10-23 17:14:23 +02:00
if ( empty ( $images_dir )) {
// No temp directory provided, so we are not able to support convertion of data:image into physical images.
$this -> error = 'NoTempDirProvidedInCMailConstructorSoCantConvertDataImgOnDisk' ;
return - 1 ;
}
$i = 0 ;
foreach ( $matches [ 1 ] as $key => $ext ) {
// We save the image to send in disk
$filecontent = $matches [ 2 ][ $key ];
2023-02-25 04:05:18 +01:00
$cid = 'cid000' . dol_hash ( $filecontent , 'md5' ); // The id must not change if image is same
2022-10-23 17:14:23 +02:00
$destfiletmp = $images_dir . '/' . $cid . '.' . $ext ;
2023-02-25 04:05:18 +01:00
if ( ! dol_is_file ( $destfiletmp )) { // If file does not exist yet (this is the case for the first email sent with a data:image inside)
dol_syslog ( " write the cid file " . $destfiletmp );
$fhandle = @ fopen ( $destfiletmp , 'w' );
if ( $fhandle ) {
$nbofbyteswrote = fwrite ( $fhandle , base64_decode ( $filecontent ));
fclose ( $fhandle );
2023-02-25 04:10:25 +01:00
dolChmod ( $destfiletmp );
2023-02-25 04:05:18 +01:00
} else {
$this -> errors [] = " Failed to open file ' " . $destfiletmp . " ' for write " ;
return - 1 ;
}
2022-10-23 17:14:23 +02:00
}
if ( file_exists ( $destfiletmp )) {
// Image full path
$this -> html_images [ $i ][ " fullpath " ] = $destfiletmp ;
// Image name
$this -> html_images [ $i ][ " name " ] = basename ( $destfiletmp );
// Content type
$this -> html_images [ $i ][ " content_type " ] = $this -> image_types [ strtolower ( $ext )];
// cid
$this -> html_images [ $i ][ " cid " ] = $cid ;
// type
$this -> html_images [ $i ][ " type " ] = 'cidfromdata' ;
2022-10-28 04:20:54 +02:00
$this -> html = str_replace ( 'src="data:image/' . $ext . ';base64,' . $filecontent . '"' , 'src="cid:' . $this -> html_images [ $i ][ " cid " ] . '"' , $this -> html );
2022-10-23 17:14:23 +02:00
}
$i ++ ;
}
return 1 ;
} else {
return 0 ;
}
}
2009-05-18 00:54:12 +02:00
/**
2015-03-19 11:47:30 +01:00
* Return a formatted address string for SMTP protocol
2011-07-20 13:07:12 +02:00
*
2016-10-24 02:02:30 +02:00
* @ param string $address Example : 'John Doe <john@doe.com>, Alan Smith <alan@smith.com>' or 'john@doe.com, alan@smith.com'
2019-03-06 20:29:58 +01:00
* @ param int $format 0 = auto , 1 = emails with <> , 2 = emails without <> , 3 = auto + label between " , 4 label or email, 5 mailto link
2016-10-24 02:02:30 +02:00
* @ param int $encode 0 = No encode name , 1 = Encode name to RFC2822
2017-04-18 01:39:06 +02:00
* @ param int $maxnumberofemail 0 = No limit . Otherwise , maximum number of emails returned ( $address may contains several email separated with ',' ) . Add '...' if there is more .
2016-10-24 02:02:30 +02:00
* @ return string If format 0 : '<john@doe.com>' or 'John Doe <john@doe.com>' or '=?UTF-8?B?Sm9obiBEb2U=?= <john@doe.com>'
* If format 1 : '<john@doe.com>'
* If format 2 : 'john@doe.com'
* If format 3 : '<john@doe.com>' or '"John Doe" <john@doe.com>' or '"=?UTF-8?B?Sm9obiBEb2U=?=" <john@doe.com>'
* If format 4 : 'John Doe' or 'john@doe.com' if no label exists
2020-09-07 10:18:17 +02:00
* If format 5 : < a href = " mailto:john@doe.com " > John Doe </ a > or < a href = " mailto:john@doe.com " > john @ doe . com </ a > if no label exists
* @ see getArrayAddress ()
2009-05-18 00:54:12 +02:00
*/
2019-02-25 22:27:04 +01:00
public static function getValidAddress ( $address , $format , $encode = 0 , $maxnumberofemail = 0 )
2009-05-18 00:54:12 +02:00
{
global $conf ;
2008-11-15 01:52:42 +01:00
2019-11-13 18:32:11 +01:00
$ret = '' ;
2004-12-28 19:34:56 +01:00
2019-11-13 18:32:11 +01:00
$arrayaddress = explode ( ',' , $address );
2008-11-15 01:52:42 +01:00
2009-05-18 00:54:12 +02:00
// Boucle sur chaque composant de l'adresse
2019-11-13 18:32:11 +01:00
$i = 0 ;
2021-01-16 14:12:09 +01:00
foreach ( $arrayaddress as $val ) {
2020-09-28 20:47:36 +02:00
$regs = array ();
2021-01-16 14:12:09 +01:00
if ( preg_match ( '/^(.*)<(.*)>$/i' , trim ( $val ), $regs )) {
2009-05-18 00:54:12 +02:00
$name = trim ( $regs [ 1 ]);
$email = trim ( $regs [ 2 ]);
2020-05-21 15:05:19 +02:00
} else {
2009-05-18 00:54:12 +02:00
$name = '' ;
$email = trim ( $val );
2007-04-01 04:56:53 +02:00
}
2009-05-18 00:54:12 +02:00
2021-01-16 14:12:09 +01:00
if ( $email ) {
2017-04-18 01:39:06 +02:00
$i ++ ;
2017-08-24 02:02:00 +02:00
2019-11-13 18:32:11 +01:00
$newemail = '' ;
2020-09-07 10:18:17 +02:00
if ( $format == 5 ) {
$newemail = $name ? $name : $email ;
$newemail = '<a href="mailto:' . $email . '">' . $newemail . '</a>' ;
}
2021-01-16 14:12:09 +01:00
if ( $format == 4 ) {
2019-11-13 18:32:11 +01:00
$newemail = $name ? $name : $email ;
2016-10-24 02:02:30 +02:00
}
2021-01-16 14:12:09 +01:00
if ( $format == 2 ) {
2019-11-13 18:32:11 +01:00
$newemail = $email ;
2009-05-18 00:54:12 +02:00
}
2021-01-16 14:12:09 +01:00
if ( $format == 1 || $format == 3 ) {
2019-11-13 18:32:11 +01:00
$newemail = '<' . $email . '>' ;
2009-05-18 00:54:12 +02:00
}
2021-01-16 14:12:09 +01:00
if ( $format == 0 || $format == 3 ) {
if ( ! empty ( $conf -> global -> MAIN_MAIL_NO_FULL_EMAIL )) {
$newemail = '<' . $email . '>' ;
} elseif ( ! $name ) {
$newemail = '<' . $email . '>' ;
} else {
$newemail = ( $format == 3 ? '"' : '' ) . ( $encode ? self :: encodetorfc2822 ( $name ) : $name ) . ( $format == 3 ? '"' : '' ) . ' <' . $email . '>' ;
}
2009-05-18 00:54:12 +02:00
}
2007-04-01 04:56:53 +02:00
2019-11-13 18:32:11 +01:00
$ret = ( $ret ? $ret . ',' : '' ) . $newemail ;
2017-04-18 01:39:06 +02:00
2016-10-24 02:02:30 +02:00
// Stop if we have too much records
2021-01-16 14:12:09 +01:00
if ( $maxnumberofemail && $i >= $maxnumberofemail ) {
if ( count ( $arrayaddress ) > $maxnumberofemail ) {
$ret .= '...' ;
}
2017-04-18 01:39:06 +02:00
break ;
2016-10-24 02:02:30 +02:00
}
2009-05-18 00:54:12 +02:00
}
2006-08-06 20:34:37 +02:00
}
2008-11-15 01:52:42 +01:00
2009-05-18 00:54:12 +02:00
return $ret ;
}
2016-04-16 18:15:03 +02:00
2017-04-18 01:39:06 +02:00
/**
* Return a formatted array of address string for SMTP protocol
*
* @ param string $address Example : 'John Doe <john@doe.com>, Alan Smith <alan@smith.com>' or 'john@doe.com, alan@smith.com'
* @ return array array of email => name
2019-12-13 15:52:08 +01:00
* @ see getValidAddress ()
2017-04-18 01:39:06 +02:00
*/
2021-07-29 10:51:51 +02:00
public static function getArrayAddress ( $address )
2017-04-18 01:39:06 +02:00
{
global $conf ;
2019-11-13 18:32:11 +01:00
$ret = array ();
2017-04-18 01:39:06 +02:00
2019-11-13 18:32:11 +01:00
$arrayaddress = explode ( ',' , $address );
2017-04-18 01:39:06 +02:00
// Boucle sur chaque composant de l'adresse
2021-01-16 14:12:09 +01:00
foreach ( $arrayaddress as $val ) {
if ( preg_match ( '/^(.*)<(.*)>$/i' , trim ( $val ), $regs )) {
2017-04-18 01:39:06 +02:00
$name = trim ( $regs [ 1 ]);
$email = trim ( $regs [ 2 ]);
2020-05-21 15:05:19 +02:00
} else {
2017-04-18 01:39:06 +02:00
$name = null ;
$email = trim ( $val );
}
2019-11-13 18:32:11 +01:00
$ret [ $email ] = empty ( $conf -> global -> MAIN_MAIL_NO_FULL_EMAIL ) ? $name : null ;
2017-04-18 01:39:06 +02:00
}
return $ret ;
}
2002-04-30 12:44:42 +02:00
}