Files
ms1inscription-v5/php/inc_mail.php
2026-05-13 09:43:32 -04:00

340 lines
13 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
define('_SMTP_HOST', 'localhost');
define('_SMTPAuth', false);
//define('_SMTP_USER', 'ms1inscription@progiweb.ca');
//define('_SMTP_PASSWORD', 'airstream911');
define('_SMTP_PORT', 25);
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
include_once APPLICATION_PATH . 'plugins/PHPMailer-6.5.1/src/Exception.php';
include_once APPLICATION_PATH . 'plugins/PHPMailer-6.5.1/src/PHPMailer.php';
include_once APPLICATION_PATH . 'plugins/PHPMailer-6.5.1/src/SMTP.php';
include_once APPLICATION_PATH . 'php/class.Html2Text.php';
/**
* Cette fonction envoi un courriel avec PHP mailer
* @author Jean-Sébastien Proulx
* @version 2.0
* @date 2021-06-10
* @return bool
*/
function fxSendMail($strSubject, $strContent, $strMailTo, $strNameTo, $strMailFrom, $strNameFrom, $smtp = 1, $html = 1, $externe = 0, $attach = '', $blnGoDaddy = false, $strLangue ='fr') {
global $objDatabase, $vClient, $vEmail,$vDomaine,$vRepertoireFichiers;
$blnReturn = false;
$arrReturn = array(
'state' => 'error',
'message' => ''
);
//Instantiation and passing `true` enables exceptions
$objMail = new PHPMailer(true);
try {
//Server settings
$objMail->SMTPDebug = SMTP::DEBUG_OFF;
$objMail->isSMTP(); //Send using SMTP
$objMail->Host = _SMTP_HOST;
$objMail->SMTPAuth = false; //Enable SMTP authentication
// $objMail->Username = _SMTP_USER;
//$objMail->Password = _SMTP_PASSWORD;
//$objMail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
$objMail->Port = _SMTP_PORT;
$objMail->CharSet = "UTF-8";
$objMail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
if ($strLangue == 'fr') {
//To load the French version
$objMail->setLanguage('fr');
}
//Recipients
$objMail->setFrom($vEmail, fxRemoveHtml($vClient));
$objMail->AddAddress($strMailTo, $strNameTo);
if ($strMailFrom != $vEmail) {
$objMail->addReplyTo($strMailFrom, $strNameFrom);
} else {
//$objMail->addReplyTo($vEmail, fxRemoveHtml($vClient));
}
//Content
$objMail->isHTML(true);
$objMail->Subject = $strSubject;
$strContent = email_embed_images_as_cid($strContent, $objMail, [
'base_path' => $vDomaine . $vRepertoireFichiers, // si tu as des src relatifs
'max_bytes' => 1024*1024
]);
$objMail->Body = $strContent;
$objHTML = new \Html2Text\Html2Text($strContent);
$objMail->AltBody = $objHTML->getText();
$objMail->send();
$blnReturn = true;
$arrReturn['state'] = 'success';
$arrReturn['message'] = "Message was sent.";
} catch (Exception $e) {
$arrReturn['message'] = "Message could not be sent. Mailer Error: {$objMail->ErrorInfo}";
}
// Log the result
$sqlInsert = "
INSERT INTO logs_mails
SET
log_subject = '" . $objDatabase->fxEscape($strSubject) . "',
log_content = '" . $objDatabase->fxEscape($strContent) . "',
log_mail_to = '" . $objDatabase->fxEscape($strMailTo) . "',
log_name_to = '" . $objDatabase->fxEscape($strNameTo) . "',
log_mail_from = '" . $objDatabase->fxEscape($strMailFrom) . "',
log_name_from = '" . $objDatabase->fxEscape($strNameFrom) . "',
log_status = '" . $objDatabase->fxEscape($arrReturn['state']) . "',
log_message = '" . $objDatabase->fxEscape($arrReturn['message']) . "'
";
$qryInsert = $objDatabase->fxQuery($sqlInsert);
return $blnReturn;
}
// fonction envoi un courriel (JSP)
// param : sujet, corps du message, courriel destinataire, nom destinataire, courriel expéditeur, nom expéditeur, smtp (oui/non), html (oui/non)
// externe (oui/non) -> appel fxSendMail provient d'un autre site (ie, Boutique Premiere) (AJOUT: AL, Juin 2015)
// retourne : vrai ou faux
function fxSendMailOld($subject, $body, $to_mail, $to_name, $from_mail, $from_name, $smtp, $html, $externe = 0, $attach = '', $blnGoDaddy = false) {
$blnGoDaddy = filter_var(fxGetVariable('mailGD'), FILTER_VALIDATE_BOOLEAN);
$error = 0;
$strError = '';
$arrSmtp = $GLOBALS['strDebug'] = [];
require_once 'mailer/PHPMailer.php';
require_once 'mailer/SMTP.php';
require_once 'mailer/Exception.php';
require_once 'php/Html2Text.php';
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->SMTPAuth = true;
if ($blnGoDaddy) {
$mail->Host = "smtpout.secureserver.net";
$mail->Port = 25;
$mail->Username = "sendms1@progiweb.us";
$mail->Password = "airstream911";
} else {
$mail->Host = "pop.progiweb.ca";
$mail->Port = 25;
$mail->Username = "ms1inscription@progiweb.ca";
$mail->Password = "airstream911";
}
$arrSmtp['host'] = $mail->Host;
$arrSmtp['port'] = $mail->Port;
$arrSmtp['username'] = $mail->Username;
$arrSmtp['password'] = $mail->Password;
if ($externe == 0) {
$mail->SetFrom($GLOBALS['vEmail'], fxRemoveHtml($GLOBALS['vClient']));
// $from_mail="ms1inscription@progiweb.ca";
// $mail->SetFrom($from_mail, fxRemoveHtml($GLOBALS['vClient']));
$mail->Subject = fxRemoveHtml($GLOBALS['vClient']) . " | " . $subject;
}
if ($externe == 1) {
$mail->SetFrom($from_mail, $from_name);
$mail->Subject = $from_name . " | " . $subject;
}
$mail->CharSet = "UTF-8";
$mail->AddReplyTo($from_mail, $from_name);
// vérifier s'il y a des fichiers à attacher
if ($attach != '') {
$mail->AddAttachment($attach);
}
$mail->isHTML(true);
$mail->Body = $body;
$html = new \Html2Text\Html2Text($body);
$mail->AltBody = $html->getText();
$mail->AddAddress($to_mail, $to_name);
$mail->SMTPDebug = 2;
$mail->Debugoutput = function($str, $level) { $GLOBALS['strDebug'][] = "debug level $level; message: $str\n"; };
if (!$mail->send()) {
$error = 1;
$strError = print_r($mail->ErrorInfo, true);
}
fxLogMail($to_mail, $to_name, $error, $strError, print_r($GLOBALS['strDebug'], true), print_r($arrSmtp, true), $subject, $body);
// Clear all addresses and attachments for next loop
$mail->ClearAddresses();
$mail->ClearAttachments();
if ($error == 0)
return true;
else {
//fxcreer_log("Erreur lors de l'envoi du mail. (TO: $to_mail, FROM $from_mail:, SUJET: $subject)");
return false;
}
}
function fxLogMail($to_mail, $to_name, $error, $strError, $strDebug, $strSmtp, $subject, $body) {
global $objDatabase;
$sqlInsert = "INSERT INTO email_logs SET log_error = " . intval($error) . ", log_error_msg = '" . $objDatabase->fxEscape($strError) . "', log_smtp_connect = '" . $objDatabase->fxEscape($strSmtp) . "', log_smtp_debug = '" . $objDatabase->fxEscape($strDebug) . "', log_subject = '" . $objDatabase->fxEscape($subject) . "', log_message = '" . $objDatabase->fxEscape($body) . "', log_mailto = '" . $objDatabase->fxEscape($to_mail) . "', log_nameto = '" . $objDatabase->fxEscape($to_name) . "'";
$qryInsert = $objDatabase->fxQuery($sqlInsert);
return $qryInsert;
}
/**
* Convertit toutes les <img src="http(s)://..."> (et relatives) en images CID.
* Si une image est inaccessible ou trop lourde, on la retire pour éviter le "Disarmed".
*/
function email_embed_images_as_cid(string $html, PHPMailer $mail, array $opt = []): string
{
$maxBytes = $opt['max_bytes'] ?? 1024 * 1024; // 1 Mo max pour une image
// 0) Détecter si c'est vraiment du HTML
// Si strip_tags() ne change rien, on est en texte brut → on ne touche pas.
$isHtml = (strlen($html) !== strlen(strip_tags($html)));
if (!$isHtml) {
return $html;
}
// On travaille sur une copie
$originalHtml = $html;
// 1) Préparer un vrai document HTML pour DOMDocument
// - Si pas de <html>, on enveloppe dans <html><body>...
// - On force un <meta charset="UTF-8"> pour éviter que DOMDocument casse les accents.
$unwrapBody = false;
if (stripos($html, '<html') === false) {
// Fragment HTML (ex: juste un <table>, des <p>, etc.)
$html = '<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body>' . $html . '</body></html>';
$unwrapBody = true;
} else {
// Document HTML complet : on s'assure qu'il a un charset UTF-8
if (stripos($html, 'charset=') === false) {
$html = preg_replace(
'#<head([^>]*)>#i',
'<head$1><meta charset="UTF-8">',
$html,
1,
$count
);
if ($count === 0) {
// pas de <head>, on colle la meta au début
$html = '<meta charset="UTF-8">' . $html;
}
}
}
// 2) Charger dans DOMDocument en UTF-8
libxml_use_internal_errors(true);
$doc = new DOMDocument('1.0', 'UTF-8');
$loaded = $doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
libxml_clear_errors();
if (!$loaded) {
// Si DOMDocument n'arrive pas à parser, on ne casse rien → on renvoie l'original
return $originalHtml;
}
$xp = new DOMXPath($doc);
// 3) Traiter toutes les <img>
foreach ($xp->query('//img[@src]') as $img) {
/** @var DOMElement $img */
$src = trim($img->getAttribute('src'));
if ($src === '' || stripos($src, 'cid:') === 0 || stripos($src, 'data:') === 0) {
continue; // déjà safe ou inline
}
$binary = null;
$mime = null;
$tmpPath = null;
// a) src absolu http(s)
if (preg_match('#^https?://#i', $src)) {
$binary = @file_get_contents($src);
if ($binary === false || strlen($binary) === 0 || strlen($binary) > $maxBytes) {
// Image introuvable ou trop grosse → on enlève l'image
$img->parentNode->removeChild($img);
continue;
}
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->buffer($binary) ?: 'application/octet-stream';
if (strpos($mime, 'image/') !== 0) {
$img->parentNode->removeChild($img);
continue;
}
$ext = explode('/', $mime)[1] ?? 'bin';
$cid = 'img' . bin2hex(random_bytes(8));
$tmpPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $cid . '.' . $ext;
file_put_contents($tmpPath, $binary);
$mail->addEmbeddedImage($tmpPath, $cid, basename($tmpPath), 'base64', $mime);
$img->setAttribute('src', 'cid:' . $cid);
continue;
}
// b) src relatif (ex: "images/logo.png" ou "/images/logo.png")
$fsPath = null;
if ($src[0] === '/') {
$fsPath = rtrim($_SERVER['DOCUMENT_ROOT'] ?? '', '/') . $src;
} else {
$basePath = $opt['base_path'] ?? null;
$fsPath = $basePath ? rtrim($basePath, '/') . '/' . $src : null;
}
if ($fsPath && is_file($fsPath)) {
$mime = mime_content_type($fsPath) ?: 'image/png';
$cid = 'img' . bin2hex(random_bytes(8));
$mail->addEmbeddedImage($fsPath, $cid, basename($fsPath), 'base64', $mime);
$img->setAttribute('src', 'cid:' . $cid);
} else {
// Image introuvable → on enlève l<img> pour éviter les "disarmed"
$img->parentNode->removeChild($img);
}
}
// 4) (Optionnel) retirer les <link> vers des polices externes (ex: Google Fonts)
foreach ($xp->query('//link[@href]') as $link) {
$href = $link->getAttribute('href');
if (stripos($href, 'fonts.googleapis.com') !== false) {
$link->parentNode->removeChild($link);
}
}
// 5) Récupérer le HTML final
if ($unwrapBody) {
// On avait enveloppé dans <body>...</body> → on ne renvoie que le contenu du body
$bodyList = $doc->getElementsByTagName('body');
if ($bodyList->length > 0) {
$body = $bodyList->item(0);
$result = '';
foreach ($body->childNodes as $child) {
$result .= $doc->saveHTML($child);
}
return $result;
}
}
// Cas document complet : on renvoie tout
return $doc->saveHTML();
}