2015-10-30 15:37:48 +01:00
< ? php
/*
* 2007 - 2015 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License ( OSL 3.0 )
* that is bundled with this package in the file LICENSE . txt .
* It is also available through the world - wide - web at this URL :
* http :// opensource . org / licenses / osl - 3.0 . php
* If you did not receive a copy of the license and are unable to
* obtain it through the world - wide - web , please send an email
* to license @ prestashop . com so we can send you a copy immediately .
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future . If you wish to customize PrestaShop for your
* needs please refer to http :// www . prestashop . com for more information .
*
* @ author PrestaShop SA < contact @ prestashop . com >
* @ copyright 2007 - 2015 PrestaShop SA
* @ license http :// opensource . org / licenses / osl - 3.0 . php Open Software License ( OSL 3.0 )
* International Registered Trademark & Property of PrestaShop SA
*/
include_once ( _PS_SWIFT_DIR_ . 'Swift.php' );
include_once ( _PS_SWIFT_DIR_ . 'Swift/Connection/SMTP.php' );
include_once ( _PS_SWIFT_DIR_ . 'Swift/Connection/NativeMail.php' );
include_once ( _PS_SWIFT_DIR_ . 'Swift/Plugin/Decorator.php' );
class Mail extends MailCore
{
public $id ;
/** @var string Recipient */
public $recipient ;
/** @var string Template */
public $template ;
/** @var string Subject */
public $subject ;
/** @var unsigned integer Language ID */
public $id_lang ;
/** @var timestamp Date */
public $date_add ;
/**
* @ see ObjectModel :: $definition
*/
public static $definition = array (
'table' => 'mail' ,
'primary' => 'id_mail' ,
'fields' => array (
'recipient' => array ( 'type' => self :: TYPE_STRING , 'validate' => 'isEmail' , 'copy_post' => false , 'required' => true , 'size' => 126 ),
'template' => array ( 'type' => self :: TYPE_STRING , 'validate' => 'isTplName' , 'copy_post' => false , 'required' => true , 'size' => 62 ),
'subject' => array ( 'type' => self :: TYPE_STRING , 'validate' => 'isMailSubject' , 'copy_post' => false , 'required' => true , 'size' => 254 ),
'id_lang' => array ( 'type' => self :: TYPE_INT , 'validate' => 'isUnsignedId' , 'copy_post' => false , 'required' => true ),
'date_add' => array ( 'type' => self :: TYPE_DATE , 'validate' => 'isDate' , 'copy_post' => false , 'required' => true ),
),
);
const TYPE_HTML = 1 ;
const TYPE_TEXT = 2 ;
const TYPE_BOTH = 3 ;
/**
* Send Email
*
* @ param int $id_lang Language of the email ( to translate the template )
* @ param string $template Template : the name of template not be a var but a string !
* @ param string $subject
* @ param string $template_vars
* @ param string $to
* @ param string $to_name
* @ param string $from
* @ param string $from_name
* @ param array $file_attachment Array with three parameters ( content , mime and name ) . You can use an array of array to attach multiple files
* @ param bool $modeSMTP
* @ param string $template_path
* @ param bool $die
* @ param string $bcc Bcc recipient
*/
public static function Send ( $id_lang , $template , $subject , $template_vars , $to ,
$to_name = null , $from = null , $from_name = null , $file_attachment = null , $mode_smtp = null ,
$template_path = _PS_MAIL_DIR_ , $die = false , $id_shop = null , $bcc = null , $reply_to = null )
{
if ( ! $id_shop )
$id_shop = Context :: getContext () -> shop -> id ;
$configuration = Configuration :: getMultiple ( array (
'PS_SHOP_EMAIL' ,
'PS_MAIL_METHOD' ,
'PS_MAIL_SERVER' ,
'PS_MAIL_USER' ,
'PS_MAIL_PASSWD' ,
'PS_SHOP_NAME' ,
'PS_MAIL_SMTP_ENCRYPTION' ,
'PS_MAIL_SMTP_PORT' ,
'PS_MAIL_TYPE'
), null , null , $id_shop );
// Returns immediatly if emails are deactivated
if ( $configuration [ 'PS_MAIL_METHOD' ] == 3 )
return true ;
$theme_path = _PS_THEME_DIR_ ;
// Get the path of theme by id_shop if exist
if ( is_numeric ( $id_shop ) && $id_shop )
{
$shop = new Shop (( int ) $id_shop );
$theme_name = $shop -> getTheme ();
if ( _THEME_NAME_ != $theme_name )
$theme_path = _PS_ROOT_DIR_ . '/themes/' . $theme_name . '/' ;
}
if ( ! isset ( $configuration [ 'PS_MAIL_SMTP_ENCRYPTION' ]))
$configuration [ 'PS_MAIL_SMTP_ENCRYPTION' ] = 'off' ;
if ( ! isset ( $configuration [ 'PS_MAIL_SMTP_PORT' ]))
$configuration [ 'PS_MAIL_SMTP_PORT' ] = 'default' ;
// Sending an e-mail can be of vital importance for the merchant, when his password is lost for example, so we must not die but do our best to send the e-mail
if ( ! isset ( $from ) || ! Validate :: isEmail ( $from ))
$from = $configuration [ 'PS_SHOP_EMAIL' ];
if ( ! Validate :: isEmail ( $from ))
$from = null ;
// $from_name is not that important, no need to die if it is not valid
if ( ! isset ( $from_name ) || ! Validate :: isMailName ( $from_name ))
$from_name = $configuration [ 'PS_SHOP_NAME' ];
if ( ! Validate :: isMailName ( $from_name ))
$from_name = null ;
// It would be difficult to send an e-mail if the e-mail is not valid, so this time we can die if there is a problem
if ( ! is_array ( $to ) && ! Validate :: isEmail ( $to ))
{
Tools :: dieOrLog ( Tools :: displayError ( 'Error: parameter "to" is corrupted' ), $die );
return false ;
}
if ( ! is_array ( $template_vars ))
$template_vars = array ();
// Do not crash for this error, that may be a complicated customer name
if ( is_string ( $to_name ) && ! empty ( $to_name ) && ! Validate :: isMailName ( $to_name ))
$to_name = null ;
if ( ! Validate :: isTplName ( $template ))
{
Tools :: dieOrLog ( Tools :: displayError ( 'Error: invalid e-mail template' ), $die );
return false ;
}
if ( ! Validate :: isMailSubject ( $subject ))
{
Tools :: dieOrLog ( Tools :: displayError ( 'Error: invalid e-mail subject' ), $die );
return false ;
}
/* Construct multiple recipients list if needed */
$to_list = new Swift_RecipientList ();
if ( is_array ( $to ) && isset ( $to ))
{
foreach ( $to as $key => $addr )
{
$addr = trim ( $addr );
if ( ! Validate :: isEmail ( $addr ))
{
Tools :: dieOrLog ( Tools :: displayError ( 'Error: invalid e-mail address' ), $die );
return false ;
}
if ( is_array ( $to_name ) && $to_name && is_array ( $to_name ) && Validate :: isGenericName ( $to_name [ $key ]))
$to_name = $to_name [ $key ];
$to_name = (( $to_name == null || $to_name == $addr ) ? '' : self :: mimeEncode ( $to_name ));
$to_list -> addTo ( $addr , $to_name );
}
$to_plugin = $to [ 0 ];
}
else
{
/* Simple recipient, one address */
$to_plugin = $to ;
$to_name = (( $to_name == null || $to_name == $to ) ? '' : self :: mimeEncode ( $to_name ));
$to_list -> addTo ( $to , $to_name );
}
if ( isset ( $bcc ))
$to_list -> addBcc ( $bcc );
try {
/* Connect with the appropriate configuration */
if ( $configuration [ 'PS_MAIL_METHOD' ] == 2 )
{
if ( empty ( $configuration [ 'PS_MAIL_SERVER' ]) || empty ( $configuration [ 'PS_MAIL_SMTP_PORT' ]))
{
Tools :: dieOrLog ( Tools :: displayError ( 'Error: invalid SMTP server or SMTP port' ), $die );
return false ;
}
$connection = new Swift_Connection_SMTP (
$configuration [ 'PS_MAIL_SERVER' ],
$configuration [ 'PS_MAIL_SMTP_PORT' ],
$configuration [ 'PS_MAIL_SMTP_ENCRYPTION' ] == 'ssl' ? Swift_Connection_SMTP :: ENC_SSL : (( $configuration [ 'PS_MAIL_SMTP_ENCRYPTION' ] == 'tls' ? Swift_Connection_SMTP :: ENC_TLS : Swift_Connection_SMTP :: ENC_OFF ))
);
$connection -> setTimeout ( 4 );
if ( ! $connection )
return false ;
if ( ! empty ( $configuration [ 'PS_MAIL_USER' ]))
$connection -> setUsername ( $configuration [ 'PS_MAIL_USER' ]);
if ( ! empty ( $configuration [ 'PS_MAIL_PASSWD' ]))
$connection -> setPassword ( $configuration [ 'PS_MAIL_PASSWD' ]);
}
else
$connection = new Swift_Connection_NativeMail ();
if ( ! $connection )
return false ;
$swift = new Swift ( $connection , Configuration :: get ( 'PS_MAIL_DOMAIN' , null , null , $id_shop ));
/* Get templates content */
$iso = Language :: getIsoById (( int ) $id_lang );
if ( ! $iso )
{
Tools :: dieOrLog ( Tools :: displayError ( 'Error - No ISO code for email' ), $die );
return false ;
}
$iso_template = $iso . '/' . $template ;
$module_name = false ;
$override_mail = false ;
// get templatePath
if ( preg_match ( '#' . __PS_BASE_URI__ . 'modules/#' , str_replace ( DIRECTORY_SEPARATOR , '/' , $template_path )) && preg_match ( '#modules/([a-z0-9_-]+)/#ui' , str_replace ( DIRECTORY_SEPARATOR , '/' , $template_path ), $res ))
$module_name = $res [ 1 ];
if ( $module_name !== false && ( file_exists ( $theme_path . 'modules/' . $module_name . '/mails/' . $iso_template . '.txt' ) ||
file_exists ( $theme_path . 'modules/' . $module_name . '/mails/' . $iso_template . '.html' )))
$template_path = $theme_path . 'modules/' . $module_name . '/mails/' ;
elseif ( file_exists ( $theme_path . 'mails/' . $iso_template . '.txt' ) || file_exists ( $theme_path . 'mails/' . $iso_template . '.html' ))
{
$template_path = $theme_path . 'mails/' ;
$override_mail = true ;
}
if ( ! file_exists ( $template_path . $iso_template . '.txt' ) && ( $configuration [ 'PS_MAIL_TYPE' ] == Mail :: TYPE_BOTH || $configuration [ 'PS_MAIL_TYPE' ] == Mail :: TYPE_TEXT ))
{
Tools :: dieOrLog ( Tools :: displayError ( 'Error - The following e-mail template is missing:' ) . ' ' . $template_path . $iso_template . '.txt' , $die );
return false ;
}
elseif ( ! file_exists ( $template_path . $iso_template . '.html' ) && ( $configuration [ 'PS_MAIL_TYPE' ] == Mail :: TYPE_BOTH || $configuration [ 'PS_MAIL_TYPE' ] == Mail :: TYPE_HTML ))
{
Tools :: dieOrLog ( Tools :: displayError ( 'Error - The following e-mail template is missing:' ) . ' ' . $template_path . $iso_template . '.html' , $die );
return false ;
}
$template_html = file_get_contents ( $template_path . $iso_template . '.html' );
$template_txt = strip_tags ( html_entity_decode ( file_get_contents ( $template_path . $iso_template . '.txt' ), null , 'utf-8' ));
if ( $override_mail && file_exists ( $template_path . $iso . '/lang.php' ))
include_once ( $template_path . $iso . '/lang.php' );
elseif ( $module_name && file_exists ( $theme_path . 'mails/' . $iso . '/lang.php' ))
include_once ( $theme_path . 'mails/' . $iso . '/lang.php' );
elseif ( file_exists ( _PS_MAIL_DIR_ . $iso . '/lang.php' ))
include_once ( _PS_MAIL_DIR_ . $iso . '/lang.php' );
else
{
Tools :: dieOrLog ( Tools :: displayError ( 'Error - The language file is missing for:' ) . ' ' . $iso , $die );
return false ;
}
/* Create mail and attach differents parts */
$subject = '[' . Configuration :: get ( 'PS_SHOP_NAME' , null , null , $id_shop ) . '] ' . $subject ;
$message = new Swift_Message ( $subject );
$message -> setCharset ( 'utf-8' );
/* Set Message-ID - getmypid() is blocked on some hosting */
$message -> setId ( Mail :: generateId ());
$message -> headers -> setEncoding ( 'Q' );
$template_vars = array_map ( array ( 'Tools' , 'htmlentitiesDecodeUTF8' ), $template_vars );
$template_vars = array_map ( array ( 'Tools' , 'stripslashes' ), $template_vars );
if ( Configuration :: get ( 'PS_LOGO_MAIL' ) !== false && file_exists ( _PS_IMG_DIR_ . Configuration :: get ( 'PS_LOGO_MAIL' , null , null , $id_shop )))
$logo = _PS_IMG_DIR_ . Configuration :: get ( 'PS_LOGO_MAIL' , null , null , $id_shop );
else
{
if ( file_exists ( _PS_IMG_DIR_ . Configuration :: get ( 'PS_LOGO' , null , null , $id_shop )))
$logo = _PS_IMG_DIR_ . Configuration :: get ( 'PS_LOGO' , null , null , $id_shop );
else
$template_vars [ '{shop_logo}' ] = '' ;
}
ShopUrl :: cacheMainDomainForShop (( int ) $id_shop );
if (( Context :: getContext () -> link instanceof Link ) === false )
Context :: getContext () -> link = new Link ();
/* Personnalisation des mails */
2015-12-14 16:07:18 +01:00
$template_vars [ '{header_img}' ] = 'http://www.toutpratique.com/themes/toutpratique/mails/header-mail.jpg' ;
$template_vars [ '{footer_img}' ] = 'http://www.toutpratique.com/themes/toutpratique/mails/footer-mail.jpg' ;
2015-11-03 14:52:12 +01:00
$template_vars [ '{box-border-color}' ] = '#e4535d' ;
2015-10-30 15:37:48 +01:00
$template_vars [ '{box-bg-color}' ] = '#ffffff' ;
$template_vars [ '{mail-bg-color}' ] = '#f0f0f0' ;
$template_vars [ '{table-bg-color}' ] = '#ffffff' ;
2015-11-03 14:52:12 +01:00
$template_vars [ '{titre1-color}' ] = '#e4535d' ;
$template_vars [ '{titre2-color}' ] = '#e4535d ' ;
$template_vars [ '{link-color}' ] = '#e4535d' ;
2015-10-30 15:37:48 +01:00
$template_vars [ '{shop_name}' ] = Tools :: safeOutput ( Configuration :: get ( 'PS_SHOP_NAME' , null , null , $id_shop ));
$template_vars [ '{shop_url}' ] = Context :: getContext () -> link -> getPageLink ( 'index' , true , Context :: getContext () -> language -> id , null , false , $id_shop );
$template_vars [ '{my_account_url}' ] = Context :: getContext () -> link -> getPageLink ( 'my-account' , true , Context :: getContext () -> language -> id , null , false , $id_shop );
$template_vars [ '{guest_tracking_url}' ] = Context :: getContext () -> link -> getPageLink ( 'guest-tracking' , true , Context :: getContext () -> language -> id , null , false , $id_shop );
$template_vars [ '{history_url}' ] = Context :: getContext () -> link -> getPageLink ( 'history' , true , Context :: getContext () -> language -> id , null , false , $id_shop );
$template_vars [ '{color}' ] = Tools :: safeOutput ( Configuration :: get ( 'PS_MAIL_COLOR' , null , null , $id_shop ));
$swift -> attachPlugin ( new Swift_Plugin_Decorator ( array ( $to_plugin => $template_vars )), 'decorator' );
if ( $configuration [ 'PS_MAIL_TYPE' ] == Mail :: TYPE_BOTH || $configuration [ 'PS_MAIL_TYPE' ] == Mail :: TYPE_TEXT )
$message -> attach ( new Swift_Message_Part ( $template_txt , 'text/plain' , '8bit' , 'utf-8' ));
if ( $configuration [ 'PS_MAIL_TYPE' ] == Mail :: TYPE_BOTH || $configuration [ 'PS_MAIL_TYPE' ] == Mail :: TYPE_HTML )
$message -> attach ( new Swift_Message_Part ( $template_html , 'text/html' , '8bit' , 'utf-8' ));
if ( $file_attachment && ! empty ( $file_attachment ))
{
// Multiple attachments?
if ( ! is_array ( current ( $file_attachment )))
$file_attachment = array ( $file_attachment );
foreach ( $file_attachment as $attachment )
if ( isset ( $attachment [ 'content' ]) && isset ( $attachment [ 'name' ]) && isset ( $attachment [ 'mime' ]))
$message -> attach ( new Swift_Message_Attachment ( $attachment [ 'content' ], $attachment [ 'name' ], $attachment [ 'mime' ]));
}
/* Send mail */
$send = $swift -> send ( $message , $to_list , new Swift_Address ( $from , $from_name ));
$swift -> disconnect ();
ShopUrl :: resetMainDomainCache ();
if ( $send && Configuration :: get ( 'PS_LOG_EMAILS' ))
{
$mail = new Mail ();
$mail -> template = substr ( $template , 0 , 62 );
$mail -> subject = substr ( $subject , 0 , 254 );
$mail -> id_lang = ( int ) $id_lang ;
foreach ( array_merge ( $to_list -> getTo (), $to_list -> getCc (), $to_list -> getBcc ()) as $recipient )
{
$mail -> id = null ;
$mail -> recipient = substr ( $recipient -> getAddress (), 0 , 126 );
$mail -> add ();
}
}
return $send ;
}
catch ( Swift_Exception $e ) {
return false ;
}
}
public static function eraseAllLogs ()
{
return Db :: getInstance () -> execute ( 'TRUNCATE TABLE ' . _DB_PREFIX_ . 'mail' );
}
public static function sendMailTest ( $smtpChecked , $smtpServer , $content , $subject , $type , $to , $from , $smtpLogin , $smtpPassword , $smtpPort = 25 , $smtpEncryption )
{
$result = false ;
try {
if ( $smtpChecked )
{
$smtp = new Swift_Connection_SMTP ( $smtpServer , $smtpPort , ( $smtpEncryption == 'off' ) ?
Swift_Connection_SMTP :: ENC_OFF : (( $smtpEncryption == 'tls' ) ? Swift_Connection_SMTP :: ENC_TLS : Swift_Connection_SMTP :: ENC_SSL ));
$smtp -> setUsername ( $smtpLogin );
$smtp -> setpassword ( $smtpPassword );
$smtp -> setTimeout ( 5 );
$swift = new Swift ( $smtp , Configuration :: get ( 'PS_MAIL_DOMAIN' ));
}
else
$swift = new Swift ( new Swift_Connection_NativeMail (), Configuration :: get ( 'PS_MAIL_DOMAIN' ));
$message = new Swift_Message ( $subject , $content , $type );
if ( $swift -> send ( $message , $to , $from ))
$result = true ;
$swift -> disconnect ();
} catch ( Swift_ConnectionException $e ) {
$result = $e -> getMessage ();
} catch ( Swift_Message_MimeException $e ) {
$result = $e -> getMessage ();
}
return $result ;
}
/**
* This method is used to get the translation for email Object .
* For an object is forbidden to use htmlentities ,
* we have to return a sentence with accents .
*
* @ param string $string raw sentence ( write directly in file )
*/
public static function l ( $string , $id_lang = null , Context $context = null )
{
global $_LANGMAIL ;
if ( ! $context )
$context = Context :: getContext ();
if ( $id_lang == null )
$id_lang = ( ! isset ( $context -> language ) || ! is_object ( $context -> language )) ? ( int ) Configuration :: get ( 'PS_LANG_DEFAULT' ) : ( int ) $context -> language -> id ;
$iso_code = Language :: getIsoById (( int ) $id_lang );
$file_core = _PS_ROOT_DIR_ . '/mails/' . $iso_code . '/lang.php' ;
if ( Tools :: file_exists_cache ( $file_core ) && empty ( $_LANGMAIL ))
include ( $file_core );
$file_theme = _PS_THEME_DIR_ . 'mails/' . $iso_code . '/lang.php' ;
if ( Tools :: file_exists_cache ( $file_theme ))
include ( $file_theme );
if ( ! is_array ( $_LANGMAIL ))
return ( str_replace ( '"' , '"' , $string ));
$key = str_replace ( '\'' , '\\\'' , $string );
return str_replace ( '"' , '"' , stripslashes (( array_key_exists ( $key , $_LANGMAIL ) && ! empty ( $_LANGMAIL [ $key ])) ? $_LANGMAIL [ $key ] : $string ));
}
/* Rewrite of Swift_Message::generateId() without getmypid() */
protected static function generateId ( $idstring = null )
{
$midparams = array (
" utctime " => gmstrftime ( " %Y%m%d%H%M%S " ),
" randint " => mt_rand (),
" customstr " => ( preg_match ( " /^(?<! \\ .)[a-z0-9 \\ .]+(?! \\ .) \$ /iD " , $idstring ) ? $idstring : " swift " ) ,
" hostname " => ( isset ( $_SERVER [ " SERVER_NAME " ]) ? $_SERVER [ " SERVER_NAME " ] : php_uname ( " n " )),
);
return vsprintf ( " <%s.%d.%s@%s> " , $midparams );
}
public static function isMultibyte ( $data )
{
$length = strlen ( $data );
for ( $i = 0 ; $i < $length ; $i ++ )
if ( ord (( $data [ $i ])) > 128 )
return true ;
return false ;
}
public static function mimeEncode ( $string , $charset = 'UTF-8' , $newline = " \r \n " )
{
if ( ! self :: isMultibyte ( $string ) && strlen ( $string ) < 75 )
return $string ;
$charset = strtoupper ( $charset );
$start = '=?' . $charset . '?B?' ;
$end = '?=' ;
$sep = $end . $newline . ' ' . $start ;
$length = 75 - strlen ( $start ) - strlen ( $end );
$length = $length - ( $length % 4 );
if ( $charset === 'UTF-8' )
{
$parts = array ();
$maxchars = floor (( $length * 3 ) / 4 );
$stringLength = strlen ( $string );
while ( $stringLength > $maxchars )
{
$i = ( int ) $maxchars ;
$result = ord ( $string [ $i ]);
while ( $result >= 128 && $result <= 191 )
$result = ord ( $string [ -- $i ]);
$parts [] = base64_encode ( substr ( $string , 0 , $i ));
$string = substr ( $string , $i );
$stringLength = strlen ( $string );
}
$parts [] = base64_encode ( $string );
$string = implode ( $sep , $parts );
}
else
{
$string = chunk_split ( base64_encode ( $string ), $length , $sep );
$string = preg_replace ( '/' . preg_quote ( $sep ) . '$/' , '' , $string );
}
return $start . $string . $end ;
}
}