email send afetr export routine

This commit is contained in:
2026-09-23 11:40:57 +02:00
parent bb2ebcc122
commit f31ba24008
32 changed files with 1526 additions and 344 deletions
+1 -1
View File
@@ -41,7 +41,7 @@
"laravel/socialite": "^5.16", "laravel/socialite": "^5.16",
"laravel/tinker": "^2.7", "laravel/tinker": "^2.7",
"laravel/ui": "^4.0", "laravel/ui": "^4.0",
"phpmailer/phpmailer": "^6.9", "phpmailer/phpmailer": "^7.1",
"phpoffice/phpspreadsheet": "^4.1", "phpoffice/phpspreadsheet": "^4.1",
"proengsoft/laravel-jsvalidation": "^4.0.0", "proengsoft/laravel-jsvalidation": "^4.0.0",
"robmorgan/phinx": "^0.16.12", "robmorgan/phinx": "^0.16.12",
Generated
+11 -10
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "557df76fdde549210349be369d479f5d", "content-hash": "e54cf3e0bbc04b94b563b01620ac3416",
"packages": [ "packages": [
{ {
"name": "akaunting/laravel-setting", "name": "akaunting/laravel-setting",
@@ -4166,16 +4166,16 @@
}, },
{ {
"name": "phpmailer/phpmailer", "name": "phpmailer/phpmailer",
"version": "v6.9.3", "version": "v7.1.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git", "url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e" "reference": "1bc1716a507a65e039d4ac9d9adebbbd0d346e15"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2f5c94fe7493efc213f643c23b1b1c249d40f47e", "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/1bc1716a507a65e039d4ac9d9adebbbd0d346e15",
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e", "reference": "1bc1716a507a65e039d4ac9d9adebbbd0d346e15",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4189,13 +4189,14 @@
"doctrine/annotations": "^1.2.6 || ^1.13.3", "doctrine/annotations": "^1.2.6 || ^1.13.3",
"php-parallel-lint/php-console-highlighter": "^1.0.0", "php-parallel-lint/php-console-highlighter": "^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.2", "php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.3.5", "phpcompatibility/php-compatibility": "^10.0.0@dev",
"roave/security-advisories": "dev-latest", "squizlabs/php_codesniffer": "^3.13.5",
"squizlabs/php_codesniffer": "^3.7.2",
"yoast/phpunit-polyfills": "^1.0.4" "yoast/phpunit-polyfills": "^1.0.4"
}, },
"suggest": { "suggest": {
"decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication", "decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
"directorytree/imapengine": "For uploading sent messages via IMAP, see gmail example",
"ext-imap": "Needed to support advanced email address parsing according to RFC822",
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses", "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"ext-openssl": "Needed for secure SMTP sending and DKIM signing", "ext-openssl": "Needed for secure SMTP sending and DKIM signing",
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication", "greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
@@ -4235,7 +4236,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP", "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": { "support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues", "issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.3" "source": "https://github.com/PHPMailer/PHPMailer/tree/v7.1.1"
}, },
"funding": [ "funding": [
{ {
@@ -4243,7 +4244,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-11-24T18:04:13+00:00" "time": "2026-05-18T08:06:14+00:00"
}, },
{ {
"name": "phpoffice/phpspreadsheet", "name": "phpoffice/phpspreadsheet",
@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class AddNotifyExportEmailToAuthUsers extends AbstractMigration
{
public function change(): void
{
$table = $this->table('auth_users');
if (!$table->hasColumn('notify_export_email')) {
$table->addColumn('notify_export_email', 'boolean', [
'default' => true, // di default ricevono la mail
'null' => false,
'after' => 'lims_global_user_id',
])->update();
}
}
}
@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class AddAnalysisPriceToPartAnalyses extends AbstractMigration
{
public function change(): void
{
$this->table('identification_parts_analyses')
->addColumn('analysis_price', 'decimal', [
'precision' => 10,
'scale' => 2,
'null' => true,
'default' => null,
'after' => 'analysis_level',
])
->update();
}
}
+22 -1
View File
@@ -166,6 +166,7 @@
is_web_selectable: rowEl.getAttribute("data-web") === "1" ? 1 : 0, is_web_selectable: rowEl.getAttribute("data-web") === "1" ? 1 : 0,
is_accredited: is_accredited:
rowEl.getAttribute("data-accredited") === "1" ? 1 : 0, rowEl.getAttribute("data-accredited") === "1" ? 1 : 0,
analysis_price: rowEl.getAttribute("data-price") || "0",
}; };
} }
@@ -196,6 +197,10 @@
: null, : null,
is_web_selectable: payload.is_web_selectable, is_web_selectable: payload.is_web_selectable,
is_accredited: payload.is_accredited, is_accredited: payload.is_accredited,
analysis_price:
payload.analysis_price !== ""
? parseFloat(payload.analysis_price)
: null,
}); });
} }
} }
@@ -247,6 +252,7 @@
analysis_level: payload.analysis_level, analysis_level: payload.analysis_level,
is_web_selectable: payload.is_web_selectable, is_web_selectable: payload.is_web_selectable,
is_accredited: payload.is_accredited, is_accredited: payload.is_accredited,
analysis_price: payload.analysis_price,
}, },
}) })
.done(function (resp) { .done(function (resp) {
@@ -389,6 +395,17 @@
const selectable = item.SelezionabileSuWeb === true; const selectable = item.SelezionabileSuWeb === true;
const accredited = item.Accreditato === true; const accredited = item.Accreditato === true;
const level = item.Livello ?? ""; const level = item.Livello ?? "";
const rawPrice = item.Prezzo;
const priceNum =
rawPrice === null ||
rawPrice === undefined ||
rawPrice === ""
? 0
: parseFloat(String(rawPrice).replace(",", "."));
const price = isNaN(priceNum) ? 0 : priceNum;
const hasPrice = price > 0;
const searchText = ( const searchText = (
analysisName + analysisName +
" " + " " +
@@ -414,6 +431,10 @@
"</span>"; "</span>";
} }
if (!hasPrice) {
badges += '<span class="badge bg-danger">No price</span>';
}
return ` return `
<div <div
class="list-group-item analysis-analysis-item" class="list-group-item analysis-analysis-item"
@@ -423,6 +444,7 @@
data-analysis-level="${escapeHtml(level)}" data-analysis-level="${escapeHtml(level)}"
data-web="${selectable ? "1" : "0"}" data-web="${selectable ? "1" : "0"}"
data-accredited="${accredited ? "1" : "0"}" data-accredited="${accredited ? "1" : "0"}"
data-price="${escapeHtml(price)}"
data-search="${escapeHtml(searchText)}" data-search="${escapeHtml(searchText)}"
> >
<div class="fw-semibold">${escapeHtml(analysisName)}</div> <div class="fw-semibold">${escapeHtml(analysisName)}</div>
@@ -440,7 +462,6 @@
filterAnalysisList(); filterAnalysisList();
syncSelectedAnalysisRows(); syncSelectedAnalysisRows();
} }
function filterAnalysisList() { function filterAnalysisList() {
const modal = document.getElementById("analysisModal"); const modal = document.getElementById("analysisModal");
if (!modal) return; if (!modal) return;
+50
View File
@@ -0,0 +1,50 @@
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception as PHPMailerException;
require_once __DIR__ . '/../../../vendor/autoload.php'; // aggiusta il path se serve
class Mailer
{
public static function send(array $to, string $subject, string $htmlBody, ?string $altBody = null): array
{
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = env('MAIL_HOST');
$mail->SMTPAuth = true;
$mail->Username = env('MAIL_USERNAME');
$mail->Password = env('MAIL_PASSWORD');
$mail->Port = (int) env('MAIL_PORT', 465);
$enc = env('MAIL_ENCRYPTION', 'ssl');
$mail->SMTPSecure = ($enc === 'tls')
? PHPMailer::ENCRYPTION_STARTTLS
: PHPMailer::ENCRYPTION_SMTPS;
$mail->CharSet = 'UTF-8';
$mail->setFrom(env('MAIL_FROM_ADDRESS'), env('MAIL_FROM_NAME', 'SmartTRF'));
foreach ($to as $addr) {
$addr = trim((string)$addr);
if ($addr !== '' && filter_var($addr, FILTER_VALIDATE_EMAIL)) {
$mail->addAddress($addr);
}
}
if (!$mail->getToAddresses()) {
return ['ok' => false, 'error' => 'Nessun destinatario valido'];
}
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $htmlBody;
$mail->AltBody = $altBody ?: strip_tags($htmlBody);
$mail->send();
return ['ok' => true, 'error' => null];
} catch (PHPMailerException $e) {
error_log('Mailer error: ' . $mail->ErrorInfo);
return ['ok' => false, 'error' => $mail->ErrorInfo];
}
}
}
+98 -2
View File
@@ -24,6 +24,24 @@
if (overlay) overlay.style.display = "none"; if (overlay) overlay.style.display = "none";
} }
function escHtml(v) {
return String(v ?? "")
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
// Badge "No price" con tooltip dei nomi analisi (vuoto se count = 0)
function noPriceBadgeHTML(count, names) {
const n = parseInt(count, 10) || 0;
if (n <= 0) return "";
const title = (names || []).join("\n");
return `<span class="badge bg-danger no-price-badge" title="${escHtml(title)}" style="margin-left:6px; font-size:0.85em; cursor:help; vertical-align:middle;"><i class="fas fa-exclamation-triangle"></i> No price (${n})</span>`;
}
window.noPriceBadgeHTML = noPriceBadgeHTML;
function getGridRow(iddatadb) { function getGridRow(iddatadb) {
return document.querySelector(`.grid-row[data-id="${iddatadb}"]`); return document.querySelector(`.grid-row[data-id="${iddatadb}"]`);
} }
@@ -34,6 +52,29 @@
); );
} }
// Invia la mail di riepilogo per gli iddatadb processati (fire-and-forget).
// Una sola chiamata a fine export (singolo o batch).
function sendExportSummaryMail(iddatadbList) {
const ids = (iddatadbList || [])
.map((v) => parseInt(v, 10))
.filter(Boolean);
if (!ids.length) return;
const body = new URLSearchParams();
ids.forEach((id) => body.append("ids[]", id));
const tid = window.gridMeta && window.gridMeta.templateId;
if (tid) body.append("template_id", tid);
fetch("send_export_summary.php", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: body.toString(),
})
.then((r) => r.json())
.then((res) => console.log("Summary mail:", res))
.catch((err) => console.warn("Summary mail failed:", err));
}
// ── Validation ────────────────────────────────────────────────────── // ── Validation ──────────────────────────────────────────────────────
async function validateRows(rowsToValidate) { async function validateRows(rowsToValidate) {
@@ -142,6 +183,9 @@
if (idx >= 0) { if (idx >= 0) {
window.gridData[idx].status = "l"; window.gridData[idx].status = "l";
window.gridData[idx].commessaweb = data.commessaweb; window.gridData[idx].commessaweb = data.commessaweb;
window.gridData[idx].noPriceCount = data.noPriceCount || 0;
window.gridData[idx].noPriceAnalyses =
data.noPriceAnalyses || [];
} }
// Update visible DOM row // Update visible DOM row
@@ -168,6 +212,11 @@
statusCell.appendChild(cwSpan); statusCell.appendChild(cwSpan);
} }
cwSpan.textContent = data.commessaweb; cwSpan.textContent = data.commessaweb;
const npHtml = noPriceBadgeHTML(
data.noPriceCount,
data.noPriceAnalyses,
);
if (npHtml) cwSpan.insertAdjacentHTML("beforeend", npHtml);
} }
const exportBtn = gridRow.querySelector(".export-lims-btn"); const exportBtn = gridRow.querySelector(".export-lims-btn");
if (exportBtn) { if (exportBtn) {
@@ -195,8 +244,17 @@
msg.innerHTML = msg.innerHTML =
`${data.message.replace(/\n/g, "<br>")}` + `${data.message.replace(/\n/g, "<br>")}` +
`<br>ID CommessaWeb: ${data.idcommessaweb}` + `<br>ID CommessaWeb: ${data.idcommessaweb}` +
`<br>Codice CommessaWeb: ${data.commessaweb}` + `<br>Codice CommessaWeb: ${escHtml(data.commessaweb)}` +
(data.totalPhotos > 0 ? `<br>Foto: ${data.totalPhotos}` : ""); noPriceBadgeHTML(data.noPriceCount, data.noPriceAnalyses) +
(data.totalPhotos > 0 ? `<br>Foto: ${data.totalPhotos}` : "") +
(data.noPriceCount > 0
? `<div class="mt-2 small text-danger fw-semibold">Analisi senza prezzo:</div>` +
`<ul class="mb-0 small text-danger">` +
(data.noPriceAnalyses || [])
.map((n) => `<li>${escHtml(n)}</li>`)
.join("") +
`</ul>`
: "");
label.textContent = "Esportazione Completata"; label.textContent = "Esportazione Completata";
} else { } else {
msg.textContent = `Errore: ${data.message}`; msg.textContent = `Errore: ${data.message}`;
@@ -386,6 +444,8 @@
data.message || "Unknown error", data.message || "Unknown error",
); );
showExportResult(data); showExportResult(data);
// Mail di riepilogo per la singola commessa
sendExportSummaryMail([iddatadb]);
} catch (error) { } catch (error) {
if (gridRow) { if (gridRow) {
setRowExporting(gridRow, false); setRowExporting(gridRow, false);
@@ -633,6 +693,8 @@
let processed = 0, let processed = 0,
succeeded = 0, succeeded = 0,
failed = 0; failed = 0;
const exportedList = []; // { commessaweb, noPriceCount, noPriceAnalyses }
const processedIds = []; // iddatadb processati (ok o errore) per la mail
disableAllRowButtons(); disableAllRowButtons();
@@ -666,11 +728,17 @@
const gridRow = row || getGridRow(iddatadb); const gridRow = row || getGridRow(iddatadb);
if (gridRow) setRowExporting(gridRow, true); if (gridRow) setRowExporting(gridRow, true);
processedIds.push(iddatadb);
try { try {
const data = await sendExport(iddatadb, batchUuid); const data = await sendExport(iddatadb, batchUuid);
processed++; processed++;
if (data.success) { if (data.success) {
succeeded++; succeeded++;
exportedList.push({
commessaweb: data.commessaweb,
noPriceCount: data.noPriceCount || 0,
noPriceAnalyses: data.noPriceAnalyses || [],
});
} else { } else {
failed++; failed++;
const errIdx = getRowIndexByIddatadb(iddatadb); const errIdx = getRowIndexByIddatadb(iddatadb);
@@ -703,6 +771,9 @@
enableAllRowButtons(); enableAllRowButtons();
if (bar) bar.style.display = "none"; if (bar) bar.style.display = "none";
// Mail di riepilogo unica per tutto il batch processato
sendExportSummaryMail(processedIds);
// Re-render to reflect status changes, then restore error indicators // Re-render to reflect status changes, then restore error indicators
const gr = window.gridRenderer; const gr = window.gridRenderer;
if (gr) gr.renderVisibleRows(); if (gr) gr.renderVisibleRows();
@@ -730,6 +801,31 @@
msgEl.innerHTML = `Exported: <strong>${succeeded}</strong><br>Errors: <strong>${failed}</strong>`; msgEl.innerHTML = `Exported: <strong>${succeeded}</strong><br>Errors: <strong>${failed}</strong>`;
} }
if (exportedList.length) {
const npCommesse = exportedList.filter(
(x) => x.noPriceCount > 0,
).length;
msgEl.innerHTML +=
`<hr class="my-2">` +
(npCommesse > 0
? `<div class="small text-danger fw-semibold mb-1"><i class="fas fa-exclamation-triangle"></i> ${npCommesse} commesse con analisi senza prezzo</div>`
: "") +
`<div class="small fw-semibold mb-1">Commesse esportate:</div>` +
`<ul class="mb-0 ps-3">` +
exportedList
.map(
(x) =>
`<li><span style="font-family:monospace;">${escHtml(x.commessaweb || "—")}</span>` +
noPriceBadgeHTML(
x.noPriceCount,
x.noPriceAnalyses,
) +
`</li>`,
)
.join("") +
`</ul>`;
}
const modalEl = document.getElementById("exportResponseModal"); const modalEl = document.getElementById("exportResponseModal");
new bootstrap.Modal(modalEl, { keyboard: false }).show(); new bootstrap.Modal(modalEl, { keyboard: false }).show();
modalEl.addEventListener("hidden.bs.modal", cleanupBackdrop, { modalEl.addEventListener("hidden.bs.modal", cleanupBackdrop, {
+14 -1
View File
@@ -585,7 +585,7 @@ try {
// 🔹 STEP 6.3: Add Analyses (AnalisiCampione) via Campione({id})/AddAnalisi bound action // 🔹 STEP 6.3: Add Analyses (AnalisiCampione) via Campione({id})/AddAnalisi bound action
$stmt = $pdo->prepare(" $stmt = $pdo->prepare("
SELECT part_id, analysis_recordkey, analysis_name, analysis_method SELECT part_id, analysis_recordkey, analysis_name, analysis_method, analysis_price
FROM identification_parts_analyses FROM identification_parts_analyses
WHERE iddatadb = :iddatadb WHERE iddatadb = :iddatadb
ORDER BY part_id, id ORDER BY part_id, id
@@ -593,6 +593,17 @@ try {
$stmt->execute(['iddatadb' => $iddatadb]); $stmt->execute(['iddatadb' => $iddatadb]);
$analysesRows = $stmt->fetchAll(PDO::FETCH_ASSOC); $analysesRows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Analisi senza prezzo (NULL o 0), una sola volta per recordkey
$noPriceAnalyses = [];
foreach ($analysesRows as $a) {
$price = $a['analysis_price'];
if ($price === null || (float)$price <= 0) {
$rk = (string)($a['analysis_recordkey'] ?? '');
$noPriceAnalyses[$rk] = $a['analysis_name'] ?: 'Unnamed analysis';
}
}
$noPriceAnalyses = array_values($noPriceAnalyses);
$partIdToIndex = []; $partIdToIndex = [];
foreach ($parts as $idx => $part) { foreach ($parts as $idx => $part) {
$partIdToIndex[(int)$part['part_id']] = $idx; $partIdToIndex[(int)$part['part_id']] = $idx;
@@ -810,6 +821,8 @@ try {
"totalAnalyses" => $totalAnalyses, "totalAnalyses" => $totalAnalyses,
"addedAnalyses" => $addedAnalyses, "addedAnalyses" => $addedAnalyses,
"failedAnalyses" => $failedAnalyses, "failedAnalyses" => $failedAnalyses,
"noPriceCount" => count($noPriceAnalyses),
"noPriceAnalyses" => $noPriceAnalyses,
"message" => "Export successful", "message" => "Export successful",
"logFiles" => [ "logFiles" => [
"step5_create" => $logFileStep5, "step5_create" => $logFileStep5,
+8 -1
View File
@@ -588,7 +588,14 @@
: "To LIMS"; : "To LIMS";
let html = `<span class="status-badge status-${esc(st)}">${label}</span>`; let html = `<span class="status-badge status-${esc(st)}">${label}</span>`;
if (row.commessaweb) { if (row.commessaweb) {
html += `<span class="commessaweb-code" style="display:block; font-size:0.75em; color:#555; margin-top:2px;">${esc(row.commessaweb)}</span>`; const npBadge =
typeof window.noPriceBadgeHTML === "function"
? window.noPriceBadgeHTML(
row.noPriceCount,
row.noPriceAnalyses,
)
: "";
html += `<span class="commessaweb-code" style="display:block; font-size:0.75em; color:#555; margin-top:2px;">${esc(row.commessaweb)}${npBadge}</span>`;
} }
div.innerHTML = html; div.innerHTML = html;
div.classList.remove("editable-cell"); div.classList.remove("editable-cell");
+2
View File
@@ -108,6 +108,8 @@
<ul class="dropdown-menu dropdown-menu-end"> <ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item d-flex align-items-center" href="user-profile.php"><i class="bx bx-user fs-5"></i><span>Profile</span></a> <li><a class="dropdown-item d-flex align-items-center" href="user-profile.php"><i class="bx bx-user fs-5"></i><span>Profile</span></a>
</li> </li>
<li><a class="dropdown-item d-flex align-items-center" href="notification_settings.php"><i class="bx bx-user fs-5"></i><span>Notifications</span></a>
</li>
<?php if ($user->hasRole('Admin') || $user->hasRole('SuperUser')): ?> <?php if ($user->hasRole('Admin') || $user->hasRole('SuperUser')): ?>
<li> <li>
<a class="dropdown-item d-flex align-items-center" href="user-admin.php"> <a class="dropdown-item d-flex align-items-center" href="user-admin.php">
+127
View File
@@ -0,0 +1,127 @@
<?php
include('include/headscript.php');
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$userId = (int)($iduserlogin ?? 0);
// Carica le preferenze correnti dell'utente
$prefs = ['notify_export_email' => 1];
if ($userId > 0) {
$s = $pdo->prepare("SELECT notify_export_email FROM auth_users WHERE id = ? LIMIT 1");
$s->execute([$userId]);
$row = $s->fetch(PDO::FETCH_ASSOC);
if ($row) {
$prefs['notify_export_email'] = (int)($row['notify_export_email'] ?? 1);
}
}
// Flash message post-save (via querystring)
$saved = isset($_GET['saved']) && $_GET['saved'] === '1';
?>
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
<?php include('cssinclude.php'); ?>
<title>SmartTRF - Notifiche</title>
<style>
.notif-row {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
padding: 16px 0;
border-bottom: 1px solid #eef0f2;
}
.notif-row:last-child {
border-bottom: none;
}
.notif-text {
max-width: 640px;
}
.notif-text h6 {
margin: 0 0 4px;
font-size: 15px;
}
.notif-text p {
margin: 0;
font-size: 13px;
color: #6c757d;
}
.form-switch .form-check-input {
width: 2.6em;
height: 1.4em;
cursor: pointer;
}
</style>
</head>
<body>
<div class="wrapper">
<?php include('include/navbar.php'); ?>
<?php include('include/topbar.php'); ?>
<div class="page-wrapper">
<div class="page-content">
<div class="card radius-10">
<div class="card-header">
<div>
<h6 class="mb-0">Preferenze notifiche</h6>
<small class="text-muted">Scegli quali email vuoi ricevere da SmartTRF.</small>
</div>
</div>
<div class="card-body">
<?php if ($saved): ?>
<div class="alert alert-success py-2" role="alert">
<i class="fas fa-check-circle me-1"></i> Preferenze salvate.
</div>
<?php endif; ?>
<form action="update_notification_prefs.php" method="POST">
<input type="hidden" name="iduserlogin" value="<?= htmlspecialchars((string)$userId, ENT_QUOTES, 'UTF-8') ?>">
<!-- Notifica: commesse esportate -->
<div class="notif-row">
<div class="notif-text">
<h6>Ricezione email commesse esportate</h6>
<p>Ricevi un riepilogo via email al termine di ogni esportazione verso il LIMS (singola o in blocco), con l'esito di ciascuna commessa.</p>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch"
id="notify_export_email" name="notify_export_email" value="1"
<?= $prefs['notify_export_email'] === 1 ? 'checked' : '' ?>>
</div>
</div>
<!-- Qui in futuro altre notifiche, stessa struttura .notif-row -->
<div class="mt-4">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save me-1"></i> Salva preferenze
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="overlay toggle-icon"></div>
<?php include('include/footer.php'); ?>
</div>
<?php include('jsinclude.php'); ?>
</body>
</html>
+7 -2
View File
@@ -22,6 +22,8 @@ try {
$analysisLevel = isset($_POST['analysis_level']) && $_POST['analysis_level'] !== '' ? (int)$_POST['analysis_level'] : null; $analysisLevel = isset($_POST['analysis_level']) && $_POST['analysis_level'] !== '' ? (int)$_POST['analysis_level'] : null;
$isWebSelectable = isset($_POST['is_web_selectable']) ? (int)$_POST['is_web_selectable'] : 0; $isWebSelectable = isset($_POST['is_web_selectable']) ? (int)$_POST['is_web_selectable'] : 0;
$isAccredited = isset($_POST['is_accredited']) ? (int)$_POST['is_accredited'] : 0; $isAccredited = isset($_POST['is_accredited']) ? (int)$_POST['is_accredited'] : 0;
$analysisPriceRaw = str_replace(',', '.', trim((string)($_POST['analysis_price'] ?? '')));
$analysisPrice = is_numeric($analysisPriceRaw) ? round((float)$analysisPriceRaw, 2) : null;
if ($partId <= 0 || $analysisRecordkey === '') { if ($partId <= 0 || $analysisRecordkey === '') {
http_response_code(400); http_response_code(400);
@@ -42,7 +44,8 @@ try {
analysis_method, analysis_method,
analysis_level, analysis_level,
is_web_selectable, is_web_selectable,
is_accredited is_accredited,
analysis_price
) VALUES ( ) VALUES (
:part_id, :part_id,
:iddatadb, :iddatadb,
@@ -52,7 +55,8 @@ try {
:analysis_method, :analysis_method,
:analysis_level, :analysis_level,
:is_web_selectable, :is_web_selectable,
:is_accredited :is_accredited,
:analysis_price
) )
"); ");
@@ -66,6 +70,7 @@ try {
':analysis_level' => $analysisLevel, ':analysis_level' => $analysisLevel,
':is_web_selectable' => $isWebSelectable, ':is_web_selectable' => $isWebSelectable,
':is_accredited' => $isAccredited, ':is_accredited' => $isAccredited,
':analysis_price' => $analysisPrice,
]); ]);
echo json_encode([ echo json_encode([
+294
View File
@@ -0,0 +1,294 @@
<?php
include('include/headscript.php');
require_once __DIR__ . '/class/Mailer.class.php';
header('Content-Type: application/json');
/**
* Risolve [IdCliente => Nominativo] leggendo la stessa cache di search_clienti.php.
* Non chiama l'API: usa cache/clienti.json (già mantenuto aggiornato dalla ricerca clienti).
*/
function resolveClientNames(array $ids): array
{
$ids = array_values(array_filter(array_map('intval', $ids), fn($v) => $v > 0));
if (empty($ids)) return [];
$cacheFile = __DIR__ . '/cache/clienti.json';
if (!file_exists($cacheFile)) return [];
$data = json_decode((string)@file_get_contents($cacheFile), true);
$clients = $data['value'] ?? [];
if (empty($clients)) return [];
// indicizza per IdCliente
$byId = [];
foreach ($clients as $c) {
$cid = (int)($c['IdCliente'] ?? 0);
if ($cid > 0) {
$byId[$cid] = trim((string)($c['Nominativo'] ?? ''));
}
}
$out = [];
foreach ($ids as $id) {
if (isset($byId[$id]) && $byId[$id] !== '') {
$out[$id] = $byId[$id];
}
}
return $out;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// input: solo POST (endpoint che invia email — niente attivazione via URL)
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'message' => 'Metodo non consentito']);
exit;
}
$ids = $_POST['ids'] ?? [];
if (!is_array($ids)) $ids = explode(',', (string)$ids);
$ids = array_values(array_filter(array_map('intval', $ids), fn($v) => $v > 0));
$templateId = (int)($_POST['template_id'] ?? 0);
if (empty($ids)) {
echo json_encode(['success' => false, 'message' => 'Nessun id']);
exit;
}
// Fallback: se il template_id non arriva, ricavalo dalla prima commessa
if ($templateId <= 0) {
$tq = $pdo->prepare("SELECT templateid FROM datadb WHERE iddatadb = ? LIMIT 1");
$tq->execute([$ids[0]]);
$templateId = (int)$tq->fetchColumn();
}
// tutti i main field del template (possono essere fino a 2), in ordine
$mainMappingIds = [];
$templateName = '';
if ($templateId > 0) {
$s = $pdo->prepare("
SELECT id FROM template_mapping
WHERE template_id = ? AND main_field = '1' AND is_visible_import = 1
ORDER BY field_order ASC, id ASC
");
$s->execute([$templateId]);
$mainMappingIds = array_map('intval', $s->fetchAll(PDO::FETCH_COLUMN));
// nome del template per l'intestazione mail
$t = $pdo->prepare("SELECT name FROM excel_templates WHERE id = ? LIMIT 1");
$t->execute([$templateId]);
$templateName = (string)$t->fetchColumn();
}
// esiti delle commesse
$ph = implode(',', array_fill(0, count($ids), '?'));
$sql = "
SELECT d.iddatadb, d.commessaweb, d.status, d.user_id,
d.idclient, d.ClienteFatturazione,
CONCAT(u.first_name,' ',u.last_name) AS user_name,
u.email AS user_email, u.notify_export_email
FROM datadb d
LEFT JOIN auth_users u ON d.user_id = u.id
WHERE d.iddatadb IN ($ph)
";
$stmt = $pdo->prepare($sql);
$stmt->execute($ids);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($rows)) {
echo json_encode(['success' => false, 'message' => 'Righe non trovate']);
exit;
}
// --- Risoluzione nomi cliente (idclient + ClienteFatturazione) ---
$clientIdsToResolve = [];
foreach ($rows as $r) {
if (!empty($r['idclient'])) $clientIdsToResolve[(int)$r['idclient']] = true;
if (!empty($r['ClienteFatturazione'])) $clientIdsToResolve[(int)$r['ClienteFatturazione']] = true;
}
$clientNames = resolveClientNames(array_keys($clientIdsToResolve)); // [id => nome]
// helper: id cliente → nome, con fallback all'id se non risolto
$clientLabel = function ($id) use ($clientNames) {
$id = (int)$id;
if ($id <= 0) return '—';
return htmlspecialchars($clientNames[$id] ?? (string)$id);
};
// valori dei main field per ogni iddatadb — concatena i main valorizzati
$mainValues = [];
if (!empty($mainMappingIds)) {
$mph = implode(',', array_fill(0, count($mainMappingIds), '?'));
$s = $pdo->prepare("
SELECT id AS iddatadb, mapping_id, field_value
FROM import_data_details
WHERE id IN ($ph) AND mapping_id IN ($mph)
");
$s->execute(array_merge($ids, $mainMappingIds));
// raggruppa per iddatadb, mantenendo l'ordine dei main
$byRow = []; // iddatadb => [mapping_id => value]
foreach ($s->fetchAll(PDO::FETCH_ASSOC) as $r) {
$byRow[(int)$r['iddatadb']][(int)$r['mapping_id']] = $r['field_value'];
}
foreach ($byRow as $idd => $vals) {
$parts = [];
foreach ($mainMappingIds as $mid) { // ordine dei main
$v = trim((string)($vals[$mid] ?? ''));
if ($v !== '') $parts[] = $v;
}
$mainValues[$idd] = implode(' — ', $parts); // es. "descrizione — style code"
}
}
// analisi senza prezzo (NULL o 0) per ogni iddatadb
$noPriceByRow = []; // iddatadb => [ [part_number, part_description, analysis_name], ... ]
$s = $pdo->prepare("
SELECT a.iddatadb, MAX(a.analysis_name) AS analysis_name
FROM identification_parts_analyses a
WHERE a.iddatadb IN ($ph)
AND (a.analysis_price IS NULL OR a.analysis_price <= 0)
GROUP BY a.iddatadb, a.analysis_recordkey
ORDER BY a.iddatadb, analysis_name
");
$s->execute($ids);
foreach ($s->fetchAll(PDO::FETCH_ASSOC) as $r) {
$noPriceByRow[(int)$r['iddatadb']][] = $r;
}
$noPriceTotal = array_sum(array_map('count', $noPriceByRow));
// destinatari: utente/i dell'export che hanno la notifica attiva + admin fisso
$recipients = [];
foreach ($rows as $r) {
if (!empty($r['user_email']) && (int)($r['notify_export_email'] ?? 1) === 1) {
$recipients[$r['user_email']] = true;
}
}
$adminEmail = env('EXPORT_SUMMARY_ADMIN', 'admin@cesoft.io'); // sempre, indipendente dalla preferenza
if ($adminEmail) $recipients[$adminEmail] = true;
$recipients = array_keys($recipients);
// Se dopo il filtro non resta nessuno, non inviare
if (empty($recipients)) {
echo json_encode(['success' => true, 'message' => 'Nessun destinatario (notifiche disattivate)', 'recipients' => []]);
exit;
}
// conteggi
$okCount = 0;
$errCount = 0;
foreach ($rows as $r) {
if ($r['status'] === 'l') $okCount++;
elseif ($r['status'] === 'x') $errCount++;
}
$hasError = $errCount > 0;
// --- tabella righe ---
$rowsHtml = '';
foreach ($rows as $r) {
$st = $r['status'];
if ($st === 'l') {
$label = 'Inviata';
$bg = '#e6f4ea';
$col = '#1e7e34';
} elseif ($st === 'x') {
$label = 'ERRORE';
$bg = '#fdecea';
$col = '#c0392b';
} else {
$label = htmlspecialchars((string)$st);
$bg = '#fff8e1';
$col = '#8a6d3b';
}
$commessa = htmlspecialchars($r['commessaweb'] ?: '—');
$main = htmlspecialchars($mainValues[(int)$r['iddatadb']] ?? '—');
$committente = $clientLabel($r['idclient'] ?? 0);
$fatturazione = $clientLabel($r['ClienteFatturazione'] ?? 0);
$rowsHtml .= "<tr>
<td style='padding:10px 10px;border-bottom:1px solid #eee;font-family:monospace;white-space:nowrap;vertical-align:top;'>{$commessa}</td>
<td style='padding:10px 10px;border-bottom:1px solid #eee;word-break:break-word;vertical-align:top;'>{$committente}</td>
<td style='padding:10px 10px;border-bottom:1px solid #eee;word-break:break-word;vertical-align:top;'>{$fatturazione}</td>
<td style='padding:10px 10px;border-bottom:1px solid #eee;word-break:break-word;vertical-align:top;'>{$main}</td>
<td style='padding:10px 10px;border-bottom:1px solid #eee;text-align:center;white-space:nowrap;vertical-align:top;'>
<span style='display:inline-block;padding:3px 10px;border-radius:12px;background:{$bg};color:{$col};font-weight:600;font-size:13px;'>{$label}</span>
</td>
</tr>";
// sotto-riga: solo le analisi No Price di questa commessa
$np = $noPriceByRow[(int)$r['iddatadb']] ?? [];
if (!empty($np)) {
$items = '';
foreach ($np as $n) {
$analysisName = htmlspecialchars((string)($n['analysis_name'] ?: 'Unnamed analysis'));
$items .= "<li style='margin:2px 0;'>{$analysisName}</li>";
}
$npCount = count($np);
$rowsHtml .= "<tr>
<td colspan='5' style='padding:8px 12px 12px 24px;border-bottom:1px solid #eee;background:#fff5f5;'>
<div style='margin-bottom:4px;font-size:12px;color:#c0392b;font-weight:600;'>
<span style='display:inline-block;padding:2px 8px;border-radius:10px;background:#c0392b;color:#fff;font-size:11px;'>No price</span>
&nbsp;Analisi senza prezzo ({$npCount})
</div>
<ul style='margin:0;padding-left:18px;font-size:13px;color:#555;'>{$items}</ul>
</td>
</tr>";
}
}
$headerColor = $hasError ? '#c0392b' : '#1e7e34';
$headerText = $hasError ? 'Export completato con errori' : 'Export completato con successo';
$total = count($rows);
$html = "
<div style='font-family:Arial,Helvetica,sans-serif;max-width:820px;margin:0 auto;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden;'>
<div style='background:{$headerColor};color:#fff;padding:18px 24px;'>
<h2 style='margin:0;font-size:18px;'>{$headerText}</h2>
<p style='margin:6px 0 0;font-size:13px;opacity:.9;'>Riepilogo esportazione verso LIMS" .
($templateName !== '' ? " &middot; Template: <strong>" . htmlspecialchars($templateName) . "</strong>" : "") . "</p>
<p style='margin:6px 0 0;font-size:13px;opacity:.95;'>
Committente: <strong>" . $clientLabel($rows[0]['idclient'] ?? 0) . "</strong>
&nbsp;&middot;&nbsp;
FatturazioneAvanzata: <strong>" . $clientLabel($rows[0]['ClienteFatturazione'] ?? 0) . "</strong>
</p>
</div>
<div style='padding:20px 24px;'>
<p style='margin:0 0 14px;font-size:14px;color:#333;'>
Totale commesse: <strong>{$total}</strong> &nbsp;•&nbsp;
<span style='color:#1e7e34;'>Inviate: {$okCount}</span> &nbsp;•&nbsp;
<span style='color:#c0392b;'>Errori: {$errCount}</span>" .
($noPriceTotal > 0 ? " &nbsp;•&nbsp; <span style='color:#c0392b;'>Analisi No price: {$noPriceTotal}</span>" : "") . "
</p>
<table style='width:100%;border-collapse:collapse;font-size:14px;table-layout:fixed;'>
<thead>
<tr style='background:#f5f5f5;'>
<th style='padding:10px 10px;text-align:left;border-bottom:2px solid #ddd;width:14%;'>Commessa</th>
<th style='padding:10px 10px;text-align:left;border-bottom:2px solid #ddd;width:24%;'>Committente</th>
<th style='padding:10px 10px;text-align:left;border-bottom:2px solid #ddd;width:24%;'>Fatturazione</th>
<th style='padding:10px 10px;text-align:left;border-bottom:2px solid #ddd;width:24%;'>Riferimento</th>
<th style='padding:10px 10px;text-align:center;border-bottom:2px solid #ddd;width:14%;'>Status</th>
</tr>
</thead>
<tbody>{$rowsHtml}</tbody>
</table>
" . ($hasError ? "<p style='margin:18px 0 0;padding:12px;background:#fdecea;border-left:4px solid #c0392b;color:#c0392b;font-size:13px;border-radius:4px;'>⚠️ Alcune commesse non sono state inviate al LIMS. Controlla la sezione <strong>Errors</strong> nell'applicazione per i dettagli e per rilanciarle.</p>" : "") . "
</div>
<div style='background:#fafafa;padding:14px 24px;font-size:12px;color:#999;border-top:1px solid #eee;'>
Messaggio automatico da SmartTRF — non rispondere a questa email.
</div>
</div>";
$subjectPrefix = $hasError ? '⚠️ Errori Export LIMS' : '✅ Export LIMS OK';
$subject = "{$subjectPrefix} — {$total} commesse ({$okCount} ok, {$errCount} err)";
$res = Mailer::send($recipients, $subject, $html);
echo json_encode([
'success' => $res['ok'],
'message' => $res['ok'] ? 'Mail inviata' : ('Mail non inviata: ' . $res['error']),
'recipients' => $recipients,
'counts' => ['ok' => $okCount, 'err' => $errCount, 'total' => $total],
]);
@@ -0,0 +1,38 @@
<?php
include('include/headscript.php');
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$userId = (int)($iduserlogin ?? 0);
if ($userId <= 0) {
header("Location: login.php");
exit;
}
// Ogni preferenza: colonna DB => 1 se checkbox spuntata, 0 altrimenti
$prefsMap = [
'notify_export_email' => isset($_POST['notify_export_email']) ? 1 : 0,
// in futuro: 'notify_altra_cosa' => isset($_POST['notify_altra_cosa']) ? 1 : 0,
];
try {
$sets = [];
$params = [];
foreach ($prefsMap as $col => $val) {
$sets[] = "`{$col}` = :{$col}";
$params[$col] = $val;
}
$params['id'] = $userId;
$sql = "UPDATE auth_users SET " . implode(', ', $sets) . " WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
header("Location: notification_settings.php?saved=1");
exit;
} catch (Exception $e) {
error_log("Notification prefs update error: " . $e->getMessage());
header("Location: notification_settings.php?saved=0");
exit;
}
+11 -10
View File
@@ -5806,17 +5806,17 @@
}, },
{ {
"name": "phpmailer/phpmailer", "name": "phpmailer/phpmailer",
"version": "v6.9.3", "version": "v7.1.1",
"version_normalized": "6.9.3.0", "version_normalized": "7.1.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git", "url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e" "reference": "1bc1716a507a65e039d4ac9d9adebbbd0d346e15"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2f5c94fe7493efc213f643c23b1b1c249d40f47e", "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/1bc1716a507a65e039d4ac9d9adebbbd0d346e15",
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e", "reference": "1bc1716a507a65e039d4ac9d9adebbbd0d346e15",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -5830,13 +5830,14 @@
"doctrine/annotations": "^1.2.6 || ^1.13.3", "doctrine/annotations": "^1.2.6 || ^1.13.3",
"php-parallel-lint/php-console-highlighter": "^1.0.0", "php-parallel-lint/php-console-highlighter": "^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.2", "php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.3.5", "phpcompatibility/php-compatibility": "^10.0.0@dev",
"roave/security-advisories": "dev-latest", "squizlabs/php_codesniffer": "^3.13.5",
"squizlabs/php_codesniffer": "^3.7.2",
"yoast/phpunit-polyfills": "^1.0.4" "yoast/phpunit-polyfills": "^1.0.4"
}, },
"suggest": { "suggest": {
"decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication", "decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
"directorytree/imapengine": "For uploading sent messages via IMAP, see gmail example",
"ext-imap": "Needed to support advanced email address parsing according to RFC822",
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses", "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"ext-openssl": "Needed for secure SMTP sending and DKIM signing", "ext-openssl": "Needed for secure SMTP sending and DKIM signing",
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication", "greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
@@ -5846,7 +5847,7 @@
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)", "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication" "thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
}, },
"time": "2024-11-24T18:04:13+00:00", "time": "2026-05-18T08:06:14+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@@ -5878,7 +5879,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP", "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": { "support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues", "issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.3" "source": "https://github.com/PHPMailer/PHPMailer/tree/v7.1.1"
}, },
"funding": [ "funding": [
{ {
+5 -5
View File
@@ -3,7 +3,7 @@
'name' => 'loshmis/vanguard', 'name' => 'loshmis/vanguard',
'pretty_version' => 'dev-main', 'pretty_version' => 'dev-main',
'version' => 'dev-main', 'version' => 'dev-main',
'reference' => 'b19963808e5545f0b99bf0eba214b0c85b2f4b7b', 'reference' => 'bb2ebcc1223dd084e59588774fecbca9875d9daf',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@@ -742,7 +742,7 @@
'loshmis/vanguard' => array( 'loshmis/vanguard' => array(
'pretty_version' => 'dev-main', 'pretty_version' => 'dev-main',
'version' => 'dev-main', 'version' => 'dev-main',
'reference' => 'b19963808e5545f0b99bf0eba214b0c85b2f4b7b', 'reference' => 'bb2ebcc1223dd084e59588774fecbca9875d9daf',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@@ -941,9 +941,9 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'phpmailer/phpmailer' => array( 'phpmailer/phpmailer' => array(
'pretty_version' => 'v6.9.3', 'pretty_version' => 'v7.1.1',
'version' => '6.9.3.0', 'version' => '7.1.1.0',
'reference' => '2f5c94fe7493efc213f643c23b1b1c249d40f47e', 'reference' => '1bc1716a507a65e039d4ac9d9adebbbd0d346e15',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../phpmailer/phpmailer', 'install_path' => __DIR__ . '/../phpmailer/phpmailer',
'aliases' => array(), 'aliases' => array(),
-15
View File
@@ -1,15 +0,0 @@
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = space
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
+13 -12
View File
@@ -6,9 +6,9 @@
[![Test status](https://github.com/PHPMailer/PHPMailer/workflows/Tests/badge.svg)](https://github.com/PHPMailer/PHPMailer/actions) [![Test status](https://github.com/PHPMailer/PHPMailer/workflows/Tests/badge.svg)](https://github.com/PHPMailer/PHPMailer/actions)
[![codecov.io](https://codecov.io/gh/PHPMailer/PHPMailer/branch/master/graph/badge.svg?token=iORZpwmYmM)](https://codecov.io/gh/PHPMailer/PHPMailer) [![codecov.io](https://codecov.io/gh/PHPMailer/PHPMailer/branch/master/graph/badge.svg?token=iORZpwmYmM)](https://codecov.io/gh/PHPMailer/PHPMailer)
[![Latest Stable Version](https://poser.pugx.org/phpmailer/phpmailer/v/stable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![Latest Stable Version](https://img.shields.io/packagist/v/phpmailer/phpmailer?label=stable)](https://packagist.org/packages/phpmailer/phpmailer)
[![Total Downloads](https://poser.pugx.org/phpmailer/phpmailer/downloads)](https://packagist.org/packages/phpmailer/phpmailer) [![Total Downloads](https://img.shields.io/packagist/dt/phpmailer/phpmailer)](https://packagist.org/packages/phpmailer/phpmailer)
[![License](https://poser.pugx.org/phpmailer/phpmailer/license.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![License](https://img.shields.io/github/license/PHPMailer/PHPMailer)](https://packagist.org/packages/phpmailer/phpmailer)
[![API Docs](https://github.com/phpmailer/phpmailer/workflows/Docs/badge.svg)](https://phpmailer.github.io/PHPMailer/) [![API Docs](https://github.com/phpmailer/phpmailer/workflows/Docs/badge.svg)](https://phpmailer.github.io/PHPMailer/)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/PHPMailer/PHPMailer/badge)](https://api.securityscorecards.dev/projects/github.com/PHPMailer/PHPMailer) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/PHPMailer/PHPMailer/badge)](https://api.securityscorecards.dev/projects/github.com/PHPMailer/PHPMailer)
@@ -20,25 +20,26 @@
- Multipart/alternative emails for mail clients that do not read HTML email - Multipart/alternative emails for mail clients that do not read HTML email
- Add attachments, including inline - Add attachments, including inline
- Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings - Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings
- SMTP authentication with LOGIN, PLAIN, CRAM-MD5, and XOAUTH2 mechanisms over SMTPS and SMTP+STARTTLS transports - Full UTF-8 support when using servers that support `SMTPUTF8`.
- Support for iCal events in multiparts and attachments
- SMTP authentication with `LOGIN`, `PLAIN`, `CRAM-MD5`, and `XOAUTH2` mechanisms over SMTPS and SMTP+STARTTLS transports
- Validates email addresses automatically - Validates email addresses automatically
- Protects against header injection attacks - Protects against header injection attacks
- Error messages in over 50 languages! - Error messages in over 50 languages!
- DKIM and S/MIME signing support - DKIM and S/MIME signing support
- Compatible with PHP 5.5 and later, including PHP 8.2 - Compatible with PHP 5.5 and later, including PHP 8.5
- Namespaced to prevent name clashes - Namespaced to prevent name clashes
- Much more! - Much more!
## Why you might need it ## Why you might need it
Many PHP developers need to send email from their code. The only PHP function that supports this directly is [`mail()`](https://www.php.net/manual/en/function.mail.php). However, it does not provide any assistance for making use of popular features such as encryption, authentication, HTML messages, and attachments. Many PHP developers need to send email from their code. The only PHP function that supports this directly is [`mail()`](https://www.php.net/manual/en/function.mail.php). However, it does not provide any assistance for making use of popular features such as authentication, HTML messages, and attachments.
Formatting email correctly is surprisingly difficult. There are myriad overlapping (and conflicting) standards, requiring tight adherence to horribly complicated formatting and encoding rules – the vast majority of code that you'll find online that uses the `mail()` function directly is just plain wrong, if not unsafe! Formatting email correctly is surprisingly difficult. There are myriad overlapping (and conflicting) standards, requiring tight adherence to horribly complicated formatting and encoding rules – the vast majority of code that you'll find online that uses the `mail()` function directly is just plain wrong, if not unsafe!
The PHP `mail()` function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD, and macOS platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP client allows email sending on all platforms without needing a local mail server. Be aware though, that the `mail()` function should be avoided when possible; it's both faster and [safer](https://exploitbox.io/paper/Pwning-PHP-Mail-Function-For-Fun-And-RCE.html) to use SMTP to localhost. The PHP `mail()` function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD, and macOS platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP client allows email sending on all platforms without needing a local mail server. Be aware though, that the `mail()` function should be avoided when possible; it's both faster and [safer](https://exploitbox.io/paper/Pwning-PHP-Mail-Function-For-Fun-And-RCE.html) to use SMTP to localhost.
*Please* don't be tempted to do it yourself – if you don't use PHPMailer, there are many other excellent libraries that *Please* don't be tempted to do it yourself – if you don't use PHPMailer, there are many other excellent libraries that
you should look at before rolling your own. Try [SwiftMailer](https://swiftmailer.symfony.com/) you should look at before rolling your own. Try [Symfony Mailer](https://symfony.com/doc/current/mailer.html), [Laminas/Mail](https://docs.laminas.dev/laminas-mail/), [ZetaComponents](https://github.com/zetacomponents/Mail), etc.
, [Laminas/Mail](https://docs.laminas.dev/laminas-mail/), [ZetaComponents](https://github.com/zetacomponents/Mail), etc.
## License ## License
This software is distributed under the [LGPL 2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) license, along with the [GPL Cooperation Commitment](https://gplcc.github.io/gplcc/). Please read [LICENSE](https://github.com/PHPMailer/PHPMailer/blob/master/LICENSE) for information on the software availability and distribution. This software is distributed under the [LGPL 2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) license, along with the [GPL Cooperation Commitment](https://gplcc.github.io/gplcc/). Please read [LICENSE](https://github.com/PHPMailer/PHPMailer/blob/master/LICENSE) for information on the software availability and distribution.
@@ -47,7 +48,7 @@ This software is distributed under the [LGPL 2.1](https://www.gnu.org/licenses/o
PHPMailer is available on [Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), and installation via [Composer](https://getcomposer.org) is the recommended way to install PHPMailer. Just add this line to your `composer.json` file: PHPMailer is available on [Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), and installation via [Composer](https://getcomposer.org) is the recommended way to install PHPMailer. Just add this line to your `composer.json` file:
```json ```json
"phpmailer/phpmailer": "^6.9.2" "phpmailer/phpmailer": "^7.0.0"
``` ```
or run or run
@@ -74,10 +75,10 @@ require 'path/to/PHPMailer/src/PHPMailer.php';
require 'path/to/PHPMailer/src/SMTP.php'; require 'path/to/PHPMailer/src/SMTP.php';
``` ```
If you're not using the `SMTP` class explicitly (you're probably not), you don't need a `use` line for the SMTP class. Even if you're not using exceptions, you do still need to load the `Exception` class as it is used internally. If you're not using the `SMTP` class explicitly (you're probably not), you don't need a `use` line for it. Even if you're not using exceptions, you do still need to load the `Exception` class as it is used internally.
## Legacy versions ## Legacy versions
PHPMailer 5.2 (which is compatible with PHP 5.0 — 7.0) is no longer supported, even for security updates. You will find the latest version of 5.2 in the [5.2-stable branch](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable). If you're using PHP 5.5 or later (which you should be), switch to the 6.x releases. PHPMailer 5.2 (which is compatible with PHP 5.0 — 7.0) is no longer supported, even for security updates. You will find the latest version of 5.2 in the [5.2-stable branch](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable). If you're using PHP 5.5 or later (which you should be), upgrade to a later release.
### Upgrading from 5.2 ### Upgrading from 5.2
The biggest changes are that source files are now in the `src/` folder, and PHPMailer now declares the namespace `PHPMailer\PHPMailer`. This has several important effects – [read the upgrade guide](https://github.com/PHPMailer/PHPMailer/tree/master/UPGRADING.md) for more details. The biggest changes are that source files are now in the `src/` folder, and PHPMailer now declares the namespace `PHPMailer\PHPMailer`. This has several important effects – [read the upgrade guide](https://github.com/PHPMailer/PHPMailer/tree/master/UPGRADING.md) for more details.
@@ -95,7 +96,7 @@ use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP; use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception; use PHPMailer\PHPMailer\Exception;
//Load Composer's autoloader //Load Composer's autoloader (created by composer, not included with PHPMailer)
require 'vendor/autoload.php'; require 'vendor/autoload.php';
//Create an instance; passing `true` enables exceptions //Create an instance; passing `true` enables exceptions
+1 -1
View File
@@ -1 +1 @@
6.9.3 7.1.1
+8 -4
View File
@@ -42,22 +42,25 @@
"doctrine/annotations": "^1.2.6 || ^1.13.3", "doctrine/annotations": "^1.2.6 || ^1.13.3",
"php-parallel-lint/php-console-highlighter": "^1.0.0", "php-parallel-lint/php-console-highlighter": "^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.2", "php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.3.5", "phpcompatibility/php-compatibility": "^10.0.0@dev",
"roave/security-advisories": "dev-latest", "squizlabs/php_codesniffer": "^3.13.5",
"squizlabs/php_codesniffer": "^3.7.2",
"yoast/phpunit-polyfills": "^1.0.4" "yoast/phpunit-polyfills": "^1.0.4"
}, },
"suggest": { "suggest": {
"decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication", "decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
"ext-imap": "Needed to support advanced email address parsing according to RFC822",
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses", "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"ext-openssl": "Needed for secure SMTP sending and DKIM signing", "ext-openssl": "Needed for secure SMTP sending and DKIM signing",
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication", "greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication", "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
"league/oauth2-google": "Needed for Google XOAUTH2 authentication", "league/oauth2-google": "Needed for Google XOAUTH2 authentication",
"psr/log": "For optional PSR-3 debug logging", "psr/log": "For optional PSR-3 debug logging",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication", "thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)" "directorytree/imapengine": "For uploading sent messages via IMAP, see gmail example"
}, },
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"PHPMailer\\PHPMailer\\": "src/" "PHPMailer\\PHPMailer\\": "src/"
@@ -71,6 +74,7 @@
"license": "LGPL-2.1-only", "license": "LGPL-2.1-only",
"scripts": { "scripts": {
"check": "./vendor/bin/phpcs", "check": "./vendor/bin/phpcs",
"style": "./vendor/bin/phpcbf",
"test": "./vendor/bin/phpunit --no-coverage", "test": "./vendor/bin/phpunit --no-coverage",
"coverage": "./vendor/bin/phpunit", "coverage": "./vendor/bin/phpunit",
"lint": [ "lint": [
+1 -1
View File
@@ -178,5 +178,5 @@ if (!isset($_GET['code'])) {
); );
//Use this to interact with an API on the users behalf //Use this to interact with an API on the users behalf
//Use this to get a new access token if the old one expires //Use this to get a new access token if the old one expires
echo 'Refresh Token: ', htmlspecialchars($token->getRefreshToken()); echo 'Refresh Token: ', htmlspecialchars($token->getRefreshToken(), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401);
} }
@@ -34,3 +34,6 @@ $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fejlede.';
$PHPMAILER_LANG['smtp_detail'] = 'Detalje: '; $PHPMAILER_LANG['smtp_detail'] = 'Detalje: ';
$PHPMAILER_LANG['smtp_error'] = 'SMTP server fejl: '; $PHPMAILER_LANG['smtp_error'] = 'SMTP server fejl: ';
$PHPMAILER_LANG['variable_set'] = 'Kunne ikke definere eller nulstille variablen: '; $PHPMAILER_LANG['variable_set'] = 'Kunne ikke definere eller nulstille variablen: ';
$PHPMAILER_LANG['no_smtputf8'] = 'Serveren understøtter ikke SMTPUTF8 som påkrævet for at sende til Unicode adresser';
$PHPMAILER_LANG['imap_recommended'] = 'Brug af forenklet adresseparser anbefales ikke. Installer PHP IMAP udvidelsen for fuld RFC822 parsing.';
$PHPMAILER_LANG['deprecated_argument'] = 'Udfaset argument: ';
+29 -18
View File
@@ -3,24 +3,35 @@
/** /**
* Esperanto PHPMailer language file: refer to English translation for definitive list * Esperanto PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer * @package PHPMailer
* @author Robin van der Vliet <info@robinvandervliet.com>
*/ */
$PHPMAILER_LANG['authenticate'] = 'Eraro de servilo SMTP : aŭtentigo malsukcesis.'; $PHPMAILER_LANG['authenticate'] = 'SMTP-eraro: Ne eblis aŭtentigi.';
$PHPMAILER_LANG['connect_host'] = 'Eraro de servilo SMTP : konektado al servilo malsukcesis.'; $PHPMAILER_LANG['buggy_php'] = 'Via versio de PHP estas trafita de cimo, kiu povas kaŭzi difektitajn mesaĝojn. Por ripari tion, ŝanĝu al sendado per SMTP, malŝaltu la opcion mail.add_x_header en via php.ini, ŝanĝu al MacOS aŭ Linux, aŭ ĝisdatigu vian PHP al versio 7.0.17+ aŭ 7.1.3+.';
$PHPMAILER_LANG['data_not_accepted'] = 'Eraro de servilo SMTP : neĝustaj datumoj.'; $PHPMAILER_LANG['connect_host'] = 'SMTP-eraro: Ne eblis konektiĝi al la SMTP-gastiganto.';
$PHPMAILER_LANG['empty_message'] = 'Teksto de mesaĝo mankas.'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP-eraro: Datumoj ne akceptitaj.';
$PHPMAILER_LANG['empty_message'] = 'Mesaĝokorpo malplena';
$PHPMAILER_LANG['encoding'] = 'Nekonata kodoprezento: '; $PHPMAILER_LANG['encoding'] = 'Nekonata kodoprezento: ';
$PHPMAILER_LANG['execute'] = 'Lanĉi rulumadon ne eblis: '; $PHPMAILER_LANG['execute'] = 'Ne eblis plenumi: ';
$PHPMAILER_LANG['file_access'] = 'Aliro al dosiero ne sukcesis: '; $PHPMAILER_LANG['extension_missing'] = 'Kromprogramo mankas: ';
$PHPMAILER_LANG['file_open'] = 'Eraro de dosiero: malfermo neeblas: '; $PHPMAILER_LANG['file_access'] = 'Ne eblis aliri la dosieron: ';
$PHPMAILER_LANG['from_failed'] = 'Jena adreso de sendinto malsukcesis: '; $PHPMAILER_LANG['file_open'] = 'Dosiera eraro: Ne eblis malfermi la dosieron: ';
$PHPMAILER_LANG['instantiate'] = 'Genero de retmesaĝa funkcio neeblis.'; $PHPMAILER_LANG['from_failed'] = 'La sekva(j) sendinto(j) malsukcesis: ';
$PHPMAILER_LANG['invalid_address'] = 'Retadreso ne validas: '; $PHPMAILER_LANG['instantiate'] = 'Ne eblis funkciigi la retpoŝtan funkcion.';
$PHPMAILER_LANG['mailer_not_supported'] = ' mesaĝilo ne subtenata.'; $PHPMAILER_LANG['invalid_address'] = 'Nevalida adreso: ';
$PHPMAILER_LANG['provide_address'] = 'Vi devas tajpi almenaŭ unu recevontan retadreson.'; $PHPMAILER_LANG['invalid_header'] = 'Nevalida kaplinia nomo aŭ valoro';
$PHPMAILER_LANG['recipients_failed'] = 'Eraro de servilo SMTP : la jenaj poŝtrecivuloj kaŭzis eraron: '; $PHPMAILER_LANG['invalid_hostentry'] = 'Nevalida enigo de gastiganto: ';
$PHPMAILER_LANG['signing'] = 'Eraro de subskribo: '; $PHPMAILER_LANG['invalid_host'] = 'Nevalida gastiganto: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP konektado malsukcesis.'; $PHPMAILER_LANG['mailer_not_supported'] = ' retpoŝtilo ne estas subtenata.';
$PHPMAILER_LANG['smtp_error'] = 'Eraro de servilo SMTP : '; $PHPMAILER_LANG['provide_address'] = 'Vi devas provizi almenaŭ unu retpoŝtadreson de ricevonto.';
$PHPMAILER_LANG['variable_set'] = 'Variablo ne pravalorizeblas aŭ ne repravalorizeblas: '; $PHPMAILER_LANG['recipients_failed'] = 'SMTP-eraro: La sekva(j) ricevonto(j) malsukcesis: ';
$PHPMAILER_LANG['extension_missing'] = 'Mankas etendo: '; $PHPMAILER_LANG['signing'] = 'Subskriba eraro: ';
$PHPMAILER_LANG['smtp_code'] = 'SMTP-kodo: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Pliaj SMTP-informoj: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'La SMTP-konektiĝo malsukcesis.';
$PHPMAILER_LANG['smtp_detail'] = 'Informoj: ';
$PHPMAILER_LANG['smtp_error'] = 'Eraro de SMTP-servilo: ';
$PHPMAILER_LANG['variable_set'] = 'Ne eblas agordi aŭ reagordi la variablon: ';
$PHPMAILER_LANG['no_smtputf8'] = 'La servilo ne subtenas SMTPUTF8, kiu estas bezonata por sendi al Unicode-adresoj.';
$PHPMAILER_LANG['imap_recommended'] = 'Uzado de la simpligita adresanalizilo ne estas rekomendita. Instalu la IMAP-kromprogramon por PHP por plena RFC822-analizado.';
$PHPMAILER_LANG['deprecated_argument'] = 'Malrekomendita argumento: ';
+4 -2
View File
@@ -9,7 +9,7 @@
*/ */
$PHPMAILER_LANG['authenticate'] = 'Error SMTP: Imposible autentificar.'; $PHPMAILER_LANG['authenticate'] = 'Error SMTP: Imposible autentificar.';
$PHPMAILER_LANG['buggy_php'] = 'Tu versión de PHP está afectada por un bug que puede resultar en mensajes corruptos. Para arreglarlo, cambia a enviar usando SMTP, deshabilita la opción mail.add_x_header en tu php.ini, cambia a MacOS o Linux, o actualiza tu PHP a la versión 7.0.17+ o 7.1.3+.'; $PHPMAILER_LANG['buggy_php'] = 'Tu versión de PHP ha sido afectada por un bug que puede resultar en mensajes corruptos. Para arreglarlo, cambia a enviar usando SMTP, deshabilita la opción mail.add_x_header en tu php.ini, cambia a MacOS o Linux, o actualiza tu PHP a la versión 7.0.17+ o 7.1.3+.';
$PHPMAILER_LANG['connect_host'] = 'Error SMTP: Imposible conectar al servidor SMTP.'; $PHPMAILER_LANG['connect_host'] = 'Error SMTP: Imposible conectar al servidor SMTP.';
$PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Datos no aceptados.'; $PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Datos no aceptados.';
$PHPMAILER_LANG['empty_message'] = 'El cuerpo del mensaje está vacío.'; $PHPMAILER_LANG['empty_message'] = 'El cuerpo del mensaje está vacío.';
@@ -18,7 +18,7 @@ $PHPMAILER_LANG['execute'] = 'Imposible ejecutar: ';
$PHPMAILER_LANG['extension_missing'] = 'Extensión faltante: '; $PHPMAILER_LANG['extension_missing'] = 'Extensión faltante: ';
$PHPMAILER_LANG['file_access'] = 'Imposible acceder al archivo: '; $PHPMAILER_LANG['file_access'] = 'Imposible acceder al archivo: ';
$PHPMAILER_LANG['file_open'] = 'Error de Archivo: Imposible abrir el archivo: '; $PHPMAILER_LANG['file_open'] = 'Error de Archivo: Imposible abrir el archivo: ';
$PHPMAILER_LANG['from_failed'] = 'La(s) siguiente(s) direcciones de remitente fallaron: '; $PHPMAILER_LANG['from_failed'] = 'La siguiente dirección de remitente falló: ';
$PHPMAILER_LANG['instantiate'] = 'Imposible crear una instancia de la función Mail.'; $PHPMAILER_LANG['instantiate'] = 'Imposible crear una instancia de la función Mail.';
$PHPMAILER_LANG['invalid_address'] = 'Imposible enviar: dirección de email inválido: '; $PHPMAILER_LANG['invalid_address'] = 'Imposible enviar: dirección de email inválido: ';
$PHPMAILER_LANG['invalid_header'] = 'Nombre o valor de encabezado no válido'; $PHPMAILER_LANG['invalid_header'] = 'Nombre o valor de encabezado no válido';
@@ -34,3 +34,5 @@ $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falló.';
$PHPMAILER_LANG['smtp_detail'] = 'Detalle: '; $PHPMAILER_LANG['smtp_detail'] = 'Detalle: ';
$PHPMAILER_LANG['smtp_error'] = 'Error del servidor SMTP: '; $PHPMAILER_LANG['smtp_error'] = 'Error del servidor SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'No se pudo configurar la variable: '; $PHPMAILER_LANG['variable_set'] = 'No se pudo configurar la variable: ';
$PHPMAILER_LANG['imap_recommended'] = 'No se recomienda usar el analizador de direcciones simplificado. Instala la extensión IMAP de PHP para un análisis RFC822 más completo.';
$PHPMAILER_LANG['deprecated_argument'] = 'Argumento obsoleto: ';
+10 -6
View File
@@ -3,27 +3,28 @@
/** /**
* Norwegian Bokmål PHPMailer language file: refer to English translation for definitive list * Norwegian Bokmål PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer * @package PHPMailer
* @author Wera AS <wordpress@wera.no>
*/ */
$PHPMAILER_LANG['authenticate'] = 'SMTP-feil: Kunne ikke autentiseres.'; $PHPMAILER_LANG['authenticate'] = 'SMTP-feil: Kunne ikke autentisere.';
$PHPMAILER_LANG['buggy_php'] = 'Din versjon av PHP er berørt av en feil som kan føre til ødelagte meldinger. For å løse problemet kan du bytte til SMTP, deaktivere alternativet mail.add_x_header i php.ini, bytte til MacOS eller Linux eller oppgradere PHP til versjon 7.0.17+ eller 7.1.3+.'; $PHPMAILER_LANG['buggy_php'] = 'Din versjon av PHP er påvirket av en feil som kan føre til ødelagte meldinger. For å løse problemet kan du bytte til sending via SMTP, deaktivere mail.add_x_header-alternativet i php.ini, bytte til MacOS eller Linux, eller oppgradere PHP til versjon 7.0.17+ eller 7.1.3+.';
$PHPMAILER_LANG['connect_host'] = 'SMTP-feil: Kunne ikke koble til SMTP-vert.'; $PHPMAILER_LANG['connect_host'] = 'SMTP-feil: Kunne ikke koble til SMTP-vert.';
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP-feil: data ikke akseptert.'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP-feil: data ikke akseptert.';
$PHPMAILER_LANG['empty_message'] = 'Meldingstekst mangler'; $PHPMAILER_LANG['empty_message'] = 'Meldingsinnholdet er tomt';
$PHPMAILER_LANG['encoding'] = 'Ukjent koding: '; $PHPMAILER_LANG['encoding'] = 'Ukjent koding: ';
$PHPMAILER_LANG['execute'] = 'Kunne ikke utføres: '; $PHPMAILER_LANG['execute'] = 'Kunne ikke utføres: ';
$PHPMAILER_LANG['extension_missing'] = 'Utvidelse mangler: '; $PHPMAILER_LANG['extension_missing'] = 'Utvidelse mangler: ';
$PHPMAILER_LANG['file_access'] = 'Kunne ikke få tilgang til filen: '; $PHPMAILER_LANG['file_access'] = 'Kunne ikke få tilgang til filen: ';
$PHPMAILER_LANG['file_open'] = 'Feil i fil: Kunne ikke åpne filen: '; $PHPMAILER_LANG['file_open'] = 'Feil i fil: Kunne ikke åpne filen: ';
$PHPMAILER_LANG['from_failed'] = 'Følgende Fra-adresse mislyktes: '; $PHPMAILER_LANG['from_failed'] = 'Følgende avsenderadresse mislyktes: ';
$PHPMAILER_LANG['instantiate'] = 'Kunne ikke instansiere e-postfunksjonen.'; $PHPMAILER_LANG['instantiate'] = 'Kunne ikke starte e-postfunksjonen.';
$PHPMAILER_LANG['invalid_address'] = 'Ugyldig adresse: '; $PHPMAILER_LANG['invalid_address'] = 'Ugyldig adresse: ';
$PHPMAILER_LANG['invalid_header'] = 'Ugyldig headernavn eller verdi'; $PHPMAILER_LANG['invalid_header'] = 'Ugyldig headernavn eller verdi';
$PHPMAILER_LANG['invalid_hostentry'] = 'Ugyldig vertsinngang: '; $PHPMAILER_LANG['invalid_hostentry'] = 'Ugyldig vertsinngang: ';
$PHPMAILER_LANG['invalid_host'] = 'Ugyldig vert: '; $PHPMAILER_LANG['invalid_host'] = 'Ugyldig vert: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' sender er ikke støttet.'; $PHPMAILER_LANG['mailer_not_supported'] = ' sender er ikke støttet.';
$PHPMAILER_LANG['provide_address'] = 'Du må oppgi minst én mottaker-e-postadresse.'; $PHPMAILER_LANG['provide_address'] = 'Du må oppgi minst én mottaker-e-postadresse.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP Feil: Følgende mottakeradresse feilet: '; $PHPMAILER_LANG['recipients_failed'] = 'SMTP-feil: Følgende mottakeradresser feilet: ';
$PHPMAILER_LANG['signing'] = 'Signeringsfeil: '; $PHPMAILER_LANG['signing'] = 'Signeringsfeil: ';
$PHPMAILER_LANG['smtp_code'] = 'SMTP-kode: '; $PHPMAILER_LANG['smtp_code'] = 'SMTP-kode: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Ytterligere SMTP-info: '; $PHPMAILER_LANG['smtp_code_ex'] = 'Ytterligere SMTP-info: ';
@@ -31,3 +32,6 @@
$PHPMAILER_LANG['smtp_detail'] = 'Detaljer: '; $PHPMAILER_LANG['smtp_detail'] = 'Detaljer: ';
$PHPMAILER_LANG['smtp_error'] = 'SMTP-serverfeil: '; $PHPMAILER_LANG['smtp_error'] = 'SMTP-serverfeil: ';
$PHPMAILER_LANG['variable_set'] = 'Kan ikke angi eller tilbakestille variabel: '; $PHPMAILER_LANG['variable_set'] = 'Kan ikke angi eller tilbakestille variabel: ';
$PHPMAILER_LANG['no_smtputf8'] = 'Serveren støtter ikke SMTPUTF8, som er nødvendig for å sende til Unicode-adresser.';
$PHPMAILER_LANG['imap_recommended'] = 'Det anbefales ikke å bruke forenklet adresseanalyse. Installer PHP IMAP-utvidelsen for full RFC822-analyse.';
$PHPMAILER_LANG['deprecated_argument'] = 'Avviklet argument: ';
+11 -7
View File
@@ -4,10 +4,11 @@
* Dutch PHPMailer language file: refer to PHPMailer.php for definitive list. * Dutch PHPMailer language file: refer to PHPMailer.php for definitive list.
* @package PHPMailer * @package PHPMailer
* @author Tuxion <team@tuxion.nl> * @author Tuxion <team@tuxion.nl>
* @author Robin van der Vliet <info@robinvandervliet.com>
*/ */
$PHPMAILER_LANG['authenticate'] = 'SMTP-fout: authenticatie mislukt.'; $PHPMAILER_LANG['authenticate'] = 'SMTP-fout: authenticatie mislukt.';
$PHPMAILER_LANG['buggy_php'] = 'PHP versie gededecteerd die onderhavig is aan een bug die kan resulteren in gecorrumpeerde berichten. Om dit te voorkomen, gebruik SMTP voor het verzenden van berichten, zet de mail.add_x_header optie in uw php.ini file uit, gebruik MacOS of Linux, of pas de gebruikte PHP versie aan naar versie 7.0.17+ or 7.1.3+.'; $PHPMAILER_LANG['buggy_php'] = 'PHP-versie gedetecteerd die onderhevig is aan een bug die kan resulteren in gecorrumpeerde berichten. Om dit te voorkomen, gebruik SMTP voor het verzenden van berichten, zet de optie mail.add_x_header in uw php.ini uit, gebruik MacOS of Linux, of pas de gebruikte PHP-versie aan naar versie 7.0.17+ or 7.1.3+.';
$PHPMAILER_LANG['connect_host'] = 'SMTP-fout: kon niet verbinden met SMTP-host.'; $PHPMAILER_LANG['connect_host'] = 'SMTP-fout: kon niet verbinden met SMTP-host.';
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP-fout: data niet geaccepteerd.'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP-fout: data niet geaccepteerd.';
$PHPMAILER_LANG['empty_message'] = 'Berichttekst is leeg'; $PHPMAILER_LANG['empty_message'] = 'Berichttekst is leeg';
@@ -16,19 +17,22 @@ $PHPMAILER_LANG['execute'] = 'Kon niet uitvoeren: ';
$PHPMAILER_LANG['extension_missing'] = 'Extensie afwezig: '; $PHPMAILER_LANG['extension_missing'] = 'Extensie afwezig: ';
$PHPMAILER_LANG['file_access'] = 'Kreeg geen toegang tot bestand: '; $PHPMAILER_LANG['file_access'] = 'Kreeg geen toegang tot bestand: ';
$PHPMAILER_LANG['file_open'] = 'Bestandsfout: kon bestand niet openen: '; $PHPMAILER_LANG['file_open'] = 'Bestandsfout: kon bestand niet openen: ';
$PHPMAILER_LANG['from_failed'] = 'Het volgende afzendersadres is mislukt: '; $PHPMAILER_LANG['from_failed'] = 'Het volgende afzenderadres is mislukt: ';
$PHPMAILER_LANG['instantiate'] = 'Kon mailfunctie niet initialiseren.'; $PHPMAILER_LANG['instantiate'] = 'Kon mailfunctie niet initialiseren.';
$PHPMAILER_LANG['invalid_address'] = 'Ongeldig adres: '; $PHPMAILER_LANG['invalid_address'] = 'Ongeldig adres: ';
$PHPMAILER_LANG['invalid_header'] = 'Ongeldige header naam of waarde'; $PHPMAILER_LANG['invalid_header'] = 'Ongeldige headernaam of -waarde';
$PHPMAILER_LANG['invalid_hostentry'] = 'Ongeldige hostentry: '; $PHPMAILER_LANG['invalid_hostentry'] = 'Ongeldige hostentry: ';
$PHPMAILER_LANG['invalid_host'] = 'Ongeldige host: '; $PHPMAILER_LANG['invalid_host'] = 'Ongeldige host: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer wordt niet ondersteund.'; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer wordt niet ondersteund.';
$PHPMAILER_LANG['provide_address'] = 'Er moet minstens één ontvanger worden opgegeven.'; $PHPMAILER_LANG['provide_address'] = 'Er moet minstens één ontvanger worden opgegeven.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP-fout: de volgende ontvangers zijn mislukt: '; $PHPMAILER_LANG['recipients_failed'] = 'SMTP-fout: de volgende ontvangers zijn mislukt: ';
$PHPMAILER_LANG['signing'] = 'Signeerfout: '; $PHPMAILER_LANG['signing'] = 'Signeerfout: ';
$PHPMAILER_LANG['smtp_code'] = 'SMTP code: '; $PHPMAILER_LANG['smtp_code'] = 'SMTP-code: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Aanvullende SMTP informatie: '; $PHPMAILER_LANG['smtp_code_ex'] = 'Aanvullende SMTP-informatie: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Verbinding mislukt.'; $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP-verbinding mislukt.';
$PHPMAILER_LANG['smtp_detail'] = 'Detail: '; $PHPMAILER_LANG['smtp_detail'] = 'Detail: ';
$PHPMAILER_LANG['smtp_error'] = 'SMTP-serverfout: '; $PHPMAILER_LANG['smtp_error'] = 'SMTP-serverfout: ';
$PHPMAILER_LANG['variable_set'] = 'Kan de volgende variabele niet instellen of resetten: '; $PHPMAILER_LANG['variable_set'] = 'Kan de volgende variabele niet instellen of herstellen: ';
$PHPMAILER_LANG['no_smtputf8'] = 'De server ondersteunt geen SMTPUTF8 dat nodig is om naar Unicode-adressen te sturen.';
$PHPMAILER_LANG['imap_recommended'] = 'Het gebruik van de vereenvoudigde adresparser is niet aanbevolen. Installeer de IMAP-extensie voor PHP voor volledige RFC822-ondersteuning.';
$PHPMAILER_LANG['deprecated_argument'] = 'Verouderd argument: ';
+22 -22
View File
@@ -5,29 +5,29 @@
* @package PHPMailer * @package PHPMailer
*/ */
$PHPMAILER_LANG['authenticate'] = 'Błąd SMTP: Nie można przeprowadzić uwierzytelnienia.'; $PHPMAILER_LANG['authenticate'] = 'Błąd SMTP: nie udało się przeprowadzić uwierzytelnienia.';
$PHPMAILER_LANG['buggy_php'] = 'Twoja wersja PHP zawiera błąd, który może powodować uszkodzenie wiadomości. Aby go naprawić, przełącz się na wysyłanie za pomocą SMTP, wyłącz opcję mail.add_x_header w php.ini, przełącz się na MacOS lub Linux lub zaktualizuj PHP do wersji 7.0.17+ lub 7.1.3+.'; $PHPMAILER_LANG['buggy_php'] = 'Używana wersja PHP zawiera błąd, który może powodować uszkodzenie wiadomości. Aby temu zapobiec, użyj wysyłki przez SMTP, wyłącz opcję mail.add_x_header w php.ini, przejdź na macOS lub Linux, lub zaktualizuj PHP do wersji 7.0.17+ albo 7.1.3+.';
$PHPMAILER_LANG['connect_host'] = 'Błąd SMTP: Nie można połączyć się z wybranym hostem.'; $PHPMAILER_LANG['connect_host'] = 'Błąd SMTP: nie udało się połączyć z serwerem (hostem).';
$PHPMAILER_LANG['data_not_accepted'] = 'Błąd SMTP: Dane nie zostały przyjęte.'; $PHPMAILER_LANG['data_not_accepted'] = 'Błąd SMTP: dane wiadomości nie zostały przyjęte przez serwer.';
$PHPMAILER_LANG['empty_message'] = 'Wiadomość jest pusta.'; $PHPMAILER_LANG['empty_message'] = 'Nie można wysłać pustej wiadomości.';
$PHPMAILER_LANG['encoding'] = 'Błędny sposób kodowania znaków: '; $PHPMAILER_LANG['encoding'] = 'Nieobsługiwane kodowanie znaków: ';
$PHPMAILER_LANG['execute'] = 'Nie można uruchomić: '; $PHPMAILER_LANG['execute'] = 'Nie udało się uruchomić polecenia: ';
$PHPMAILER_LANG['extension_missing'] = 'Brakujące rozszerzenie: '; $PHPMAILER_LANG['extension_missing'] = 'Brak wymaganego rozszerzenia PHP: ';
$PHPMAILER_LANG['file_access'] = 'Brak dostępu do pliku: '; $PHPMAILER_LANG['file_access'] = 'Brak dostępu do pliku: ';
$PHPMAILER_LANG['file_open'] = 'Nie można otworzyć pliku: '; $PHPMAILER_LANG['file_open'] = 'Nie udało się otworzyć pliku: ';
$PHPMAILER_LANG['from_failed'] = 'Następujący adres nadawcy jest nieprawidłowy lub nie istnieje: '; $PHPMAILER_LANG['from_failed'] = 'Nieprawidłowy adres nadawcy: ';
$PHPMAILER_LANG['instantiate'] = 'Nie można wywołać funkcji mail(). Sprawdź konfigurację serwera.'; $PHPMAILER_LANG['instantiate'] = 'Nie można zainicjować funkcji mail(). Sprawdź konfigurację serwera.';
$PHPMAILER_LANG['invalid_address'] = 'Nie można wysłać wiadomości, ' . 'następujący adres odbiorcy jest nieprawidłowy lub nie istnieje: '; $PHPMAILER_LANG['invalid_address'] = 'Nie można wysłać wiadomości. Nieprawidłowy adres odbiorcy: ';
$PHPMAILER_LANG['invalid_header'] = 'Nieprawidłowa nazwa lub wartość nagłówka'; $PHPMAILER_LANG['invalid_header'] = 'Nieprawidłowa nazwa lub wartość nagłówka.';
$PHPMAILER_LANG['invalid_hostentry'] = 'Nieprawidłowy wpis hosta: '; $PHPMAILER_LANG['invalid_hostentry'] = 'Nieprawidłowy wpis hosta: ';
$PHPMAILER_LANG['invalid_host'] = 'Nieprawidłowy host: '; $PHPMAILER_LANG['invalid_host'] = 'Nieprawidłowa nazwa hosta: ';
$PHPMAILER_LANG['provide_address'] = 'Należy podać prawidłowy adres email odbiorcy.'; $PHPMAILER_LANG['provide_address'] = 'Musisz podać co najmniej jeden prawidłowy adres e-mail odbiorcy.';
$PHPMAILER_LANG['mailer_not_supported'] = 'Wybrana metoda wysyłki wiadomości nie jest obsługiwana.'; $PHPMAILER_LANG['mailer_not_supported'] = 'Wybrana metoda wysyłki wiadomości nie jest obsługiwana.';
$PHPMAILER_LANG['recipients_failed'] = 'Błąd SMTP: Następujący odbiorcy są nieprawidłowi lub nie istnieją: '; $PHPMAILER_LANG['recipients_failed'] = 'Błąd SMTP: nie udało się wysłać do następujących odbiorców: ';
$PHPMAILER_LANG['signing'] = 'Błąd podpisywania wiadomości: '; $PHPMAILER_LANG['signing'] = 'Błąd podpisywania wiadomości cyfrowo: ';
$PHPMAILER_LANG['smtp_code'] = 'Kod SMTP: '; $PHPMAILER_LANG['smtp_code'] = 'Kod odpowiedzi SMTP: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Dodatkowe informacje SMTP: '; $PHPMAILER_LANG['smtp_code_ex'] = 'Dodatkowe informacje serwera SMTP: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'Wywołanie funkcji SMTP Connect() zostało zakończone niepowodzeniem.'; $PHPMAILER_LANG['smtp_connect_failed'] = 'Nie udało się nawiązać połączenia za pomocą SMTP Connect().';
$PHPMAILER_LANG['smtp_detail'] = 'Szczegóły: '; $PHPMAILER_LANG['smtp_detail'] = 'Szczegóły błędu: ';
$PHPMAILER_LANG['smtp_error'] = 'Błąd SMTP: '; $PHPMAILER_LANG['smtp_error'] = 'Błąd serwera SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'Nie można ustawić lub zmodyfikować zmiennej: '; $PHPMAILER_LANG['variable_set'] = 'Nie można ustawić lub zmodyfikować zmiennej: ';
+24 -17
View File
@@ -3,25 +3,32 @@
/** /**
* Portuguese (European) PHPMailer language file: refer to English translation for definitive list * Portuguese (European) PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer * @package PHPMailer
* @author Jonadabe <jonadabe@hotmail.com> * @author João Vieira <mail@joaovieira.eu>
*/ */
$PHPMAILER_LANG['authenticate'] = 'Erro do SMTP: Não foi possível realizar a autenticação.'; $PHPMAILER_LANG['authenticate'] = 'Erro SMTP: Falha na autenticação.';
$PHPMAILER_LANG['connect_host'] = 'Erro do SMTP: Não foi possível realizar ligação com o servidor SMTP.'; $PHPMAILER_LANG['buggy_php'] = 'A sua versão do PHP tem um bug que pode causar mensagens corrompidas. Para resolver, utilize o envio por SMTP, desative a opção mail.add_x_header no ficheiro php.ini, mude para MacOS ou Linux, ou atualize o PHP para a versão 7.0.17+ ou 7.1.3+.';
$PHPMAILER_LANG['data_not_accepted'] = 'Erro do SMTP: Os dados foram rejeitados.'; $PHPMAILER_LANG['connect_host'] = 'Erro SMTP: Não foi possível ligar ao servidor SMTP.';
$PHPMAILER_LANG['empty_message'] = 'A mensagem no e-mail está vazia.'; $PHPMAILER_LANG['data_not_accepted'] = 'Erro SMTP: Dados não aceites.';
$PHPMAILER_LANG['empty_message'] = 'A mensagem de e-mail está vazia.';
$PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: '; $PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: ';
$PHPMAILER_LANG['execute'] = 'Não foi possível executar: '; $PHPMAILER_LANG['execute'] = 'Não foi possível executar: ';
$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder o ficheiro: ';
$PHPMAILER_LANG['file_open'] = 'Abertura do ficheiro: Não foi possível abrir o ficheiro: ';
$PHPMAILER_LANG['from_failed'] = 'Ocorreram falhas nos endereços dos seguintes remententes: ';
$PHPMAILER_LANG['instantiate'] = 'Não foi possível iniciar uma instância da função mail.';
$PHPMAILER_LANG['invalid_address'] = 'Não foi enviado nenhum e-mail para o endereço de e-mail inválido: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer não é suportado.';
$PHPMAILER_LANG['provide_address'] = 'Tem de fornecer pelo menos um endereço como destinatário do e-mail.';
$PHPMAILER_LANG['recipients_failed'] = 'Erro do SMTP: O endereço do seguinte destinatário falhou: ';
$PHPMAILER_LANG['signing'] = 'Erro ao assinar: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falhou.';
$PHPMAILER_LANG['smtp_error'] = 'Erro de servidor SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: ';
$PHPMAILER_LANG['extension_missing'] = 'Extensão em falta: '; $PHPMAILER_LANG['extension_missing'] = 'Extensão em falta: ';
$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder ao ficheiro: ';
$PHPMAILER_LANG['file_open'] = 'Erro ao abrir o ficheiro: ';
$PHPMAILER_LANG['from_failed'] = 'O envio falhou para o seguinte endereço do remetente: ';
$PHPMAILER_LANG['instantiate'] = 'Não foi possível instanciar a função mail.';
$PHPMAILER_LANG['invalid_address'] = 'Endereço de e-mail inválido: ';
$PHPMAILER_LANG['invalid_header'] = 'Nome ou valor do cabeçalho inválido.';
$PHPMAILER_LANG['invalid_hostentry'] = 'Entrada de host inválida: ';
$PHPMAILER_LANG['invalid_host'] = 'Host inválido: ';
$PHPMAILER_LANG['mailer_not_supported'] = 'O cliente de e-mail não é suportado.';
$PHPMAILER_LANG['provide_address'] = 'Deve fornecer pelo menos um endereço de destinatário.';
$PHPMAILER_LANG['recipients_failed'] = 'Erro SMTP: Falha no envio para os seguintes destinatários: ';
$PHPMAILER_LANG['signing'] = 'Erro ao assinar: ';
$PHPMAILER_LANG['smtp_code'] = 'Código SMTP: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Informações adicionais SMTP: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'Falha na função SMTP connect().';
$PHPMAILER_LANG['smtp_detail'] = 'Detalhes: ';
$PHPMAILER_LANG['smtp_error'] = 'Erro do servidor SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: ';
@@ -8,6 +8,7 @@
* @author Mehmet Benlioğlu * @author Mehmet Benlioğlu
* @author @yasinaydin * @author @yasinaydin
* @author Ogün Karakuş * @author Ogün Karakuş
* @author Mustafa Deniz Buksur
*/ */
$PHPMAILER_LANG['authenticate'] = 'SMTP Hatası: Oturum açılamadı.'; $PHPMAILER_LANG['authenticate'] = 'SMTP Hatası: Oturum açılamadı.';
@@ -36,3 +37,7 @@ $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP connect() fonksiyonu başarısı
$PHPMAILER_LANG['smtp_detail'] = 'SMTP SMTP Detayı: '; $PHPMAILER_LANG['smtp_detail'] = 'SMTP SMTP Detayı: ';
$PHPMAILER_LANG['smtp_error'] = 'SMTP sunucu hatası: '; $PHPMAILER_LANG['smtp_error'] = 'SMTP sunucu hatası: ';
$PHPMAILER_LANG['variable_set'] = 'Değişken ayarlanamadı ya da sıfırlanamadı: '; $PHPMAILER_LANG['variable_set'] = 'Değişken ayarlanamadı ya da sıfırlanamadı: ';
$PHPMAILER_LANG['no_smtputf8'] = 'Unicode adreslere gönderim için gereken SMTPUTF8 desteği sunucu tarafından desteklenmiyor.';
$PHPMAILER_LANG['imap_recommended'] = 'Basitleştirilmiş adres ayrıştırıcısını kullanmanız önerilmez. ' .
'Tam RFC822 ayrıştırma için PHP IMAP eklentisini yükleyin.';
$PHPMAILER_LANG['deprecated_argument'] = 'Kullanımdan kaldırılmış argüman: ';
File diff suppressed because it is too large Load Diff
+20 -6
View File
@@ -45,8 +45,9 @@ class POP3
* The POP3 PHPMailer Version number. * The POP3 PHPMailer Version number.
* *
* @var string * @var string
* @deprecated This constant will be removed in PHPMailer 8.0. Use `PHPMailer::VERSION` instead.
*/ */
const VERSION = '6.9.3'; const VERSION = '7.1.1';
/** /**
* Default POP3 port number. * Default POP3 port number.
@@ -211,9 +212,9 @@ class POP3
} else { } else {
$this->tval = (int) $timeout; $this->tval = (int) $timeout;
} }
$this->do_debug = $debug_level; $this->do_debug = (int) $debug_level;
$this->username = $username; $this->username = self::stripControls($username);
$this->password = $password; $this->password = self::stripControls($password);
//Reset the error log //Reset the error log
$this->errors = []; $this->errors = [];
//Connect //Connect
@@ -318,7 +319,8 @@ class POP3
if (empty($password)) { if (empty($password)) {
$password = $this->password; $password = $this->password;
} }
$username = self::stripControls($username);
$password = self::stripControls($password);
//Send the Username //Send the Username
$this->sendString("USER $username" . static::LE); $this->sendString("USER $username" . static::LE);
$pop3_response = $this->getResponse(); $pop3_response = $this->getResponse();
@@ -406,7 +408,7 @@ class POP3
/** /**
* Checks the POP3 server response. * Checks the POP3 server response.
* Looks for for +OK or -ERR. * Looks for +OK or -ERR.
* *
* @param string $string * @param string $string
* *
@@ -466,4 +468,16 @@ class POP3
"errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline" "errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline"
); );
} }
/**
* Strip all control chars from a string.
*
* @param $string
*
* @return string
*/
protected static function stripControls($string)
{
return preg_replace('/[\x00-\x1F\x7F]/u', '', $string);
}
} }
+118 -10
View File
@@ -34,8 +34,9 @@ class SMTP
* The PHPMailer SMTP version number. * The PHPMailer SMTP version number.
* *
* @var string * @var string
* @deprecated This constant will be removed in PHPMailer 8.0. Use `PHPMailer::VERSION` instead.
*/ */
const VERSION = '6.9.3'; const VERSION = '7.1.1';
/** /**
* SMTP line break constant. * SMTP line break constant.
@@ -159,6 +160,15 @@ class SMTP
*/ */
public $do_verp = false; public $do_verp = false;
/**
* Whether to use SMTPUTF8.
*
* @see https://www.rfc-editor.org/rfc/rfc6531
*
* @var bool
*/
public $do_smtputf8 = false;
/** /**
* The timeout value for connection, in seconds. * The timeout value for connection, in seconds.
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2. * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2.
@@ -196,6 +206,7 @@ class SMTP
'Haraka' => '/[\d]{3} Message Queued \((.*)\)/', 'Haraka' => '/[\d]{3} Message Queued \((.*)\)/',
'ZoneMTA' => '/[\d]{3} Message queued as (.*)/', 'ZoneMTA' => '/[\d]{3} Message queued as (.*)/',
'Mailjet' => '/[\d]{3} OK queued as (.*)/', 'Mailjet' => '/[\d]{3} OK queued as (.*)/',
'Gsmtp' => '/[\d]{3} 2\.0\.0 OK (.*) - gsmtp/',
]; ];
/** /**
@@ -484,7 +495,9 @@ class SMTP
//PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT //PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
//so add them back in manually if we can //so add them back in manually if we can
if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
// phpcs:ignore PHPCompatibility.Constants.NewConstants.stream_crypto_method_tlsv1_2_clientFound
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
// phpcs:ignore PHPCompatibility.Constants.NewConstants.stream_crypto_method_tlsv1_1_clientFound
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
} }
@@ -623,12 +636,49 @@ class SMTP
if (null === $OAuth) { if (null === $OAuth) {
return false; return false;
} }
try {
$oauth = $OAuth->getOauth64(); $oauth = $OAuth->getOauth64();
} catch (\Exception $e) {
//Start authentication // We catch all exceptions and convert them to PHPMailer exceptions to be able to
// handle them correctly later
throw new Exception("SMTP authentication error", 0, $e);
}
/*
* An SMTP command line can have a maximum length of 512 bytes, including the command name,
* so the base64-encoded OAUTH token has a maximum length of:
* 512 - 13 (AUTH XOAUTH2) - 2 (CRLF) = 497 bytes
* If the token is longer than that, the command and the token must be sent separately as described in
* https://www.rfc-editor.org/rfc/rfc4954#section-4
*/
if ($oauth === '') {
//Sending an empty auth token is legitimate, but it must be encoded as '='
//to indicate it's not a 2-part command
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 =', 235)) {
return false;
}
} elseif (strlen($oauth) <= 497) {
//Authenticate using a token in the initial-response part
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) { if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
return false; return false;
} }
} else {
//The token is too long, so we need to send it in two parts.
//Send the auth command without a token and expect a 334
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2', 334)) {
return false;
}
//Send the token
if (!$this->sendCommand('OAuth TOKEN', $oauth, [235, 334])) {
return false;
}
//If the server answers with 334, send an empty line and wait for a 235
if (
substr($this->last_reply, 0, 3) === '334'
&& $this->sendCommand('AUTH End', '', 235)
) {
return false;
}
}
break; break;
default: default:
$this->setError("Authentication method \"$authtype\" is not supported"); $this->setError("Authentication method \"$authtype\" is not supported");
@@ -720,6 +770,25 @@ class SMTP
} }
} }
private function iterateLines($s)
{
$start = 0;
$length = strlen($s);
for ($i = 0; $i < $length; $i++) {
$c = $s[$i];
if ($c === "\n" || $c === "\r") {
yield substr($s, $start, $i - $start);
if ($c === "\r" && $i + 1 < $length && $s[$i + 1] === "\n") {
$i++;
}
$start = $i + 1;
}
}
yield substr($s, $start);
}
/** /**
* Send an SMTP DATA command. * Send an SMTP DATA command.
* Issues a data command and sends the msg_data to the server, * Issues a data command and sends the msg_data to the server,
@@ -748,15 +817,16 @@ class SMTP
* NOTE: this does not count towards line-length limit. * NOTE: this does not count towards line-length limit.
*/ */
//Normalize line breaks before exploding //Iterate over lines with normalized line breaks
$lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data)); $lines = $this->iterateLines($msg_data);
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field /* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
* of the first line (':' separated) does not contain a space then it _should_ be a header, and we will * of the first line (':' separated) does not contain a space then it _should_ be a header, and we will
* process all lines before a blank line as headers. * process all lines before a blank line as headers.
*/ */
$field = substr($lines[0], 0, strpos($lines[0], ':')); $first_line = $lines->current();
$field = substr($first_line, 0, strpos($first_line, ':'));
$in_headers = false; $in_headers = false;
if (!empty($field) && strpos($field, ' ') === false) { if (!empty($field) && strpos($field, ' ') === false) {
$in_headers = true; $in_headers = true;
@@ -913,7 +983,15 @@ class SMTP
* $from. Returns true if successful or false otherwise. If True * $from. Returns true if successful or false otherwise. If True
* the mail transaction is started and then one or more recipient * the mail transaction is started and then one or more recipient
* commands may be called followed by a data command. * commands may be called followed by a data command.
* Implements RFC 821: MAIL <SP> FROM:<reverse-path> <CRLF>. * Implements RFC 821: MAIL <SP> FROM:<reverse-path> <CRLF> and
* two extensions, namely XVERP and SMTPUTF8.
*
* The server's EHLO response is not checked. If use of either
* extensions is enabled even though the server does not support
* that, mail submission will fail.
*
* XVERP is documented at https://www.postfix.org/VERP_README.html
* and SMTPUTF8 is specified in RFC 6531.
* *
* @param string $from Source address of this message * @param string $from Source address of this message
* *
@@ -922,10 +1000,11 @@ class SMTP
public function mail($from) public function mail($from)
{ {
$useVerp = ($this->do_verp ? ' XVERP' : ''); $useVerp = ($this->do_verp ? ' XVERP' : '');
$useSmtputf8 = ($this->do_smtputf8 ? ' SMTPUTF8' : '');
return $this->sendCommand( return $this->sendCommand(
'MAIL FROM', 'MAIL FROM',
'MAIL FROM:<' . $from . '>' . $useVerp, 'MAIL FROM:<' . $from . '>' . $useSmtputf8 . $useVerp,
250 250
); );
} }
@@ -1210,7 +1289,7 @@ class SMTP
* 3. EHLO has been sent - * 3. EHLO has been sent -
* $name == 'HELO'|'EHLO': returns the server name * $name == 'HELO'|'EHLO': returns the server name
* $name == any other string: if extension $name exists, returns True * $name == any other string: if extension $name exists, returns True
* or its options (e.g. AUTH mechanisms supported). Otherwise returns False. * or its options (e.g. AUTH mechanisms supported). Otherwise, returns False.
* *
* @param string $name Name of SMTP extension or 'HELO'|'EHLO' * @param string $name Name of SMTP extension or 'HELO'|'EHLO'
* *
@@ -1291,7 +1370,16 @@ class SMTP
//stream_select returns false when the `select` system call is interrupted //stream_select returns false when the `select` system call is interrupted
//by an incoming signal, try the select again //by an incoming signal, try the select again
if (stripos($message, 'interrupted system call') !== false) { if (
stripos($message, 'interrupted system call') !== false ||
(
// on applications with a different locale than english, the message above is not found because
// it's translated. So we also check for the SOCKET_EINTR constant which is defined under
// Windows and UNIX-like platforms (if available on the platform).
defined('SOCKET_EINTR') &&
stripos($message, 'stream_select(): Unable to select [' . SOCKET_EINTR . ']') !== false
)
) {
$this->edebug( $this->edebug(
'SMTP -> get_lines(): retrying stream_select', 'SMTP -> get_lines(): retrying stream_select',
self::DEBUG_LOWLEVEL self::DEBUG_LOWLEVEL
@@ -1364,6 +1452,26 @@ class SMTP
return $this->do_verp; return $this->do_verp;
} }
/**
* Enable or disable use of SMTPUTF8.
*
* @param bool $enabled
*/
public function setSMTPUTF8($enabled = false)
{
$this->do_smtputf8 = $enabled;
}
/**
* Get SMTPUTF8 use.
*
* @return bool
*/
public function getSMTPUTF8()
{
return $this->do_smtputf8;
}
/** /**
* Set error messages and codes. * Set error messages and codes.
* *