feat: add OpenSSL setup guide and enhance email logging functionality
This commit is contained in:
100
php/OPENSSL_SETUP.md
Normal file
100
php/OPENSSL_SETUP.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# Enabling OpenSSL Extension in PHP (Windows)
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
Your PHP installation doesn't have the OpenSSL extension enabled, which is required for secure SMTP connections (TLS/SSL).
|
||||||
|
|
||||||
|
Current error: `Unable to find the socket transport "ssl"` or `TLS/SSL transports not available`
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
### Option 1: Enable OpenSSL in php.ini (Recommended)
|
||||||
|
|
||||||
|
1. **Find your php.ini file:**
|
||||||
|
```powershell
|
||||||
|
php --ini
|
||||||
|
```
|
||||||
|
|
||||||
|
If it shows "Loaded Configuration File: (none)", you need to create one:
|
||||||
|
```powershell
|
||||||
|
# Find PHP installation directory
|
||||||
|
where.exe php
|
||||||
|
|
||||||
|
# Copy the example php.ini
|
||||||
|
cd C:\path\to\php
|
||||||
|
copy php.ini-development php.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Edit php.ini** and find this line:
|
||||||
|
```ini
|
||||||
|
;extension=openssl
|
||||||
|
```
|
||||||
|
|
||||||
|
Remove the semicolon to uncomment it:
|
||||||
|
```ini
|
||||||
|
extension=openssl
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Restart your PHP server** (or command line if using built-in server)
|
||||||
|
|
||||||
|
4. **Verify OpenSSL is enabled:**
|
||||||
|
```powershell
|
||||||
|
php -m | Select-String -Pattern "openssl"
|
||||||
|
```
|
||||||
|
|
||||||
|
Should output: `openssl`
|
||||||
|
|
||||||
|
### Option 2: Enable OpenSSL temporarily via command line
|
||||||
|
|
||||||
|
You can enable OpenSSL for a single command:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
php -d extension=openssl test_email.php
|
||||||
|
```
|
||||||
|
|
||||||
|
Or for the built-in server:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
php -d extension=openssl -S localhost:8000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 3: Install Composer and PHPMailer
|
||||||
|
|
||||||
|
If you can't modify php.ini, install PHPMailer which may handle SMTP better:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Install Composer first (https://getcomposer.org/)
|
||||||
|
# Then in the php/ directory:
|
||||||
|
composer require phpmailer/phpmailer
|
||||||
|
```
|
||||||
|
|
||||||
|
The application will automatically detect and use PHPMailer if available.
|
||||||
|
|
||||||
|
## Verifying the Fix
|
||||||
|
|
||||||
|
After enabling OpenSSL, run the test:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd C:\Users\aky547\GitHub\SemapForm\php
|
||||||
|
php test_email.php
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see:
|
||||||
|
- `Available transports: tcp, udp, ssl, tls` (or similar)
|
||||||
|
- `TLS encryption enabled successfully`
|
||||||
|
- `Email sent successfully via SMTP`
|
||||||
|
|
||||||
|
## Alternative: Use a Different SMTP Port
|
||||||
|
|
||||||
|
If you absolutely cannot enable OpenSSL, you could try:
|
||||||
|
|
||||||
|
1. Contact your email administrator to see if there's an unencrypted SMTP port (not recommended for security)
|
||||||
|
2. Use a different email solution (e.g., send via a web service API instead of SMTP)
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
On a production server (Linux/shared hosting):
|
||||||
|
|
||||||
|
- OpenSSL is usually enabled by default
|
||||||
|
- Check with `php -m | grep openssl`
|
||||||
|
- If not available, contact your hosting provider
|
||||||
|
- Most shared hosting environments have it pre-configured
|
||||||
@@ -95,13 +95,61 @@
|
|||||||
- Set environment variables through hosting control panel
|
- Set environment variables through hosting control panel
|
||||||
- Test mail() function first before adding SMTP
|
- Test mail() function first before adding SMTP
|
||||||
|
|
||||||
|
## Email Logging
|
||||||
|
|
||||||
|
The application now includes comprehensive email logging:
|
||||||
|
|
||||||
|
- **Log Location**: `php/mail.log`
|
||||||
|
- **Log Format**: `[YYYY-MM-DD HH:MM:SS] [LEVEL] Message`
|
||||||
|
- **Configuration**:
|
||||||
|
- Set `LOG_ENABLED = true` in `config.php` to enable logging
|
||||||
|
- Logs are also written to PHP error_log with `[MAIL]` prefix
|
||||||
|
|
||||||
|
### What Gets Logged
|
||||||
|
|
||||||
|
- Email send attempts with from/to/subject
|
||||||
|
- Email content length
|
||||||
|
- SMTP connection details (host, port, encryption)
|
||||||
|
- PHPMailer initialization and configuration steps
|
||||||
|
- Success/failure status for each send attempt
|
||||||
|
- Detailed error messages for failed sends
|
||||||
|
- When mail is disabled (includes full XML content)
|
||||||
|
|
||||||
|
### Viewing Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View recent log entries
|
||||||
|
tail -f php/mail.log
|
||||||
|
|
||||||
|
# View last 50 lines
|
||||||
|
tail -n 50 php/mail.log
|
||||||
|
|
||||||
|
# Search for errors
|
||||||
|
grep ERROR php/mail.log
|
||||||
|
|
||||||
|
# Search for successful sends
|
||||||
|
grep SUCCESS php/mail.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Log File Management
|
||||||
|
|
||||||
|
The log file is automatically created when needed. To rotate logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Manual rotation
|
||||||
|
mv php/mail.log php/mail.log.$(date +%Y%m%d)
|
||||||
|
touch php/mail.log
|
||||||
|
chmod 666 php/mail.log
|
||||||
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Emails not sending
|
### Emails not sending
|
||||||
1. Check `MAIL_ENABLED` is set to `true`
|
1. Check `MAIL_ENABLED` is set to `true`
|
||||||
2. Verify SMTP credentials are correct
|
2. **Check `php/mail.log`** for detailed error messages
|
||||||
3. Check server error logs: `tail -f /var/log/apache2/error.log`
|
3. Verify SMTP credentials are correct
|
||||||
4. Test with `MAIL_ENABLED=false` to see XML output in logs
|
4. Check server error logs: `tail -f /var/log/apache2/error.log`
|
||||||
|
5. Test with `MAIL_ENABLED=false` to see XML output in logs
|
||||||
|
|
||||||
### Form validation errors
|
### Form validation errors
|
||||||
- Ensure all required fields have values
|
- Ensure all required fields have values
|
||||||
|
|||||||
@@ -11,19 +11,23 @@ error_reporting(E_ALL);
|
|||||||
ini_set('display_errors', 1);
|
ini_set('display_errors', 1);
|
||||||
|
|
||||||
// Email configuration
|
// Email configuration
|
||||||
define('MAIL_ENABLED', getenv('MAIL_ENABLED') !== false ? filter_var(getenv('MAIL_ENABLED'), FILTER_VALIDATE_BOOLEAN) : true);
|
define('MAIL_ENABLED', true);//getenv('MAIL_ENABLED') !== false ? filter_var(getenv('MAIL_ENABLED'), FILTER_VALIDATE_BOOLEAN) : true);
|
||||||
define('SMTP_HOST', getenv('SMTP_HOST') ?: 'smtp.ph-freiburg.de');
|
define('SMTP_HOST', 'smtp.ph-freiburg.de');//getenv('SMTP_HOST') ?: 'smtp.ph-freiburg.de');
|
||||||
define('SMTP_PORT', getenv('SMTP_PORT') ?: 465);
|
define('SMTP_PORT', 587);//getenv('SMTP_PORT') ?: 587); // Use 587 for TLS, 465 for SSL
|
||||||
define('SMTP_ENCRYPTION', 'ssl'); // 'ssl' or 'tls' or '' for none
|
define('SMTP_ENCRYPTION', 'tls'); // 'ssl' or 'tls' or '' for none
|
||||||
define('SMTP_USERNAME', getenv('MAIL_USERNAME') ?: '');
|
define('SMTP_USERNAME', 'aky547');//getenv('MAIL_USERNAME') ?: 'aky547');
|
||||||
define('SMTP_PASSWORD', getenv('MAIL_PASSWORD') ?: '');
|
define('SMTP_PASSWORD', 'CMcDna3qPh2*n');//getenv('MAIL_PASSWORD') ?: 'CMcDna3qPh2*n');
|
||||||
define('MAIL_FROM', getenv('MAIL_FROM') ?: 'alexander.kirchner@ph-freiburg.de');
|
define('MAIL_FROM', 'alexander.kirchner@ph-freiburg.de');//getenv('MAIL_FROM') ?: 'alexander.kirchner@ph-freiburg.de');
|
||||||
define('MAIL_TO', getenv('MAIL_TO') ?: 'semesterapparate@ph-freiburg.de');
|
define('MAIL_TO', 'kirchneralexander020@gmail.com');//getenv('MAIL_TO') ?: 'kirchneralexander@proton.me');
|
||||||
|
|
||||||
// Application settings
|
// Application settings
|
||||||
define('BASE_PATH', __DIR__);
|
define('BASE_PATH', __DIR__);
|
||||||
define('STATIC_PATH', '/static');
|
define('STATIC_PATH', '/static');
|
||||||
|
|
||||||
|
// Logging configuration
|
||||||
|
define('LOG_FILE', BASE_PATH . '/mail.log');
|
||||||
|
define('LOG_ENABLED', true);
|
||||||
|
|
||||||
// Signature validation API (optional Python service)
|
// Signature validation API (optional Python service)
|
||||||
define('SIGNATURE_API_URL', getenv('SIGNATURE_API_URL') ?: 'http://localhost:8001');
|
define('SIGNATURE_API_URL', getenv('SIGNATURE_API_URL') ?: 'http://localhost:8001');
|
||||||
|
|
||||||
|
|||||||
10
php/elsa.php
10
php/elsa.php
@@ -302,8 +302,8 @@
|
|||||||
'<td><input type="text" name="herausgeber_signature[]" data-section="' + sectionId + '" placeholder="Optional"></td>' +
|
'<td><input type="text" name="herausgeber_signature[]" data-section="' + sectionId + '" placeholder="Optional"></td>' +
|
||||||
'<td><input type="number" name="herausgeber_pages_from[]" data-section="' + sectionId + '" required min="1"></td>' +
|
'<td><input type="number" name="herausgeber_pages_from[]" data-section="' + sectionId + '" required min="1"></td>' +
|
||||||
'<td><input type="number" name="herausgeber_pages_to[]" data-section="' + sectionId + '" required min="1"></td>' +
|
'<td><input type="number" name="herausgeber_pages_to[]" data-section="' + sectionId + '" required min="1"></td>' +
|
||||||
attachSignatureListeners(row);
|
|
||||||
'<td><button type="button" class="btn-icon" onclick="removeRow(\'' + rowId + '\')" title="Zeile entfernen"><span class="mdi mdi-delete"></span></button></td>';
|
'<td><button type="button" class="btn-icon" onclick="removeRow(\'' + rowId + '\')" title="Zeile entfernen"><span class="mdi mdi-delete"></span></button></td>';
|
||||||
|
attachSignatureListeners(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,7 +491,9 @@
|
|||||||
function removeMediaSection(sectionId) {
|
function removeMediaSection(sectionId) {
|
||||||
const section = document.getElementById(sectionId);
|
const section = document.getElementById(sectionId);
|
||||||
if (section) {
|
if (section) {
|
||||||
if (const rows = section.querySelectorAll('tr[id]');
|
if (confirm('Möchten Sie diese Sektion wirklich entfernen?')) {
|
||||||
|
const type = section.getAttribute('data-type');
|
||||||
|
const rows = section.querySelectorAll('tr[id]');
|
||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
const signatureInput = row.querySelector('input[name*="_signature"]');
|
const signatureInput = row.querySelector('input[name*="_signature"]');
|
||||||
if (signatureInput) {
|
if (signatureInput) {
|
||||||
@@ -504,9 +506,7 @@
|
|||||||
btn.disabled = false;
|
btn.disabled = false;
|
||||||
btn.title = 'Sektion hinzufügen';
|
btn.title = 'Sektion hinzufügen';
|
||||||
}
|
}
|
||||||
updateSubmitButton(); btn.disabled = false;
|
updateSubmitButton();
|
||||||
btn.title = 'Sektion hinzufügen';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +1,79 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once 'config.php';
|
require_once 'config.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write log message to file
|
||||||
|
*/
|
||||||
|
function writeLog($message, $level = 'INFO')
|
||||||
|
{
|
||||||
|
if (!LOG_ENABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$timestamp = date('Y-m-d H:i:s');
|
||||||
|
$logMessage = "[{$timestamp}] [{$level}] {$message}" . PHP_EOL;
|
||||||
|
|
||||||
|
// Also log to error_log for immediate visibility
|
||||||
|
error_log("[MAIL] {$message}");
|
||||||
|
|
||||||
|
// Write to log file
|
||||||
|
if (defined('LOG_FILE')) {
|
||||||
|
file_put_contents(LOG_FILE, $logMessage, FILE_APPEND | LOCK_EX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate email address
|
* Validate email address
|
||||||
*/
|
*/
|
||||||
function validateEmail($email) {
|
function validateEmail($email)
|
||||||
|
{
|
||||||
return preg_match(EMAIL_REGEX, $email);
|
return preg_match(EMAIL_REGEX, $email);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sanitize input string
|
* Sanitize input string
|
||||||
*/
|
*/
|
||||||
function sanitizeInput($input) {
|
function sanitizeInput($input)
|
||||||
|
{
|
||||||
return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
|
return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate XML from form data
|
* Generate XML from form data
|
||||||
*/
|
*/
|
||||||
function generateXML($data) {
|
function generateXML($data)
|
||||||
|
{
|
||||||
$xml = new DOMDocument('1.0', 'UTF-8');
|
$xml = new DOMDocument('1.0', 'UTF-8');
|
||||||
$xml->formatOutput = true;
|
$xml->formatOutput = true;
|
||||||
|
|
||||||
$root = $xml->createElement('form_submission');
|
$root = $xml->createElement('form_submission');
|
||||||
$xml->appendChild($root);
|
$xml->appendChild($root);
|
||||||
|
|
||||||
// Static data
|
// Static data
|
||||||
$static = $xml->createElement('static');
|
$static = $xml->createElement('static');
|
||||||
$root->appendChild($static);
|
$root->appendChild($static);
|
||||||
|
|
||||||
foreach (['name', 'lastname', 'title', 'telno', 'mail', 'apparatsname', 'subject', 'semester', 'dauerapparat'] as $field) {
|
foreach (['name', 'lastname', 'title', 'telno', 'mail', 'apparatsname', 'subject', 'semester', 'dauerapparat'] as $field) {
|
||||||
if (isset($data[$field])) {
|
if (isset($data[$field])) {
|
||||||
$element = $xml->createElement($field, htmlspecialchars($data[$field]));
|
$element = $xml->createElement($field, htmlspecialchars($data[$field]));
|
||||||
$static->appendChild($element);
|
$static->appendChild($element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($data['message'])) {
|
if (!empty($data['message'])) {
|
||||||
$messageEl = $xml->createElement('message', htmlspecialchars($data['message']));
|
$messageEl = $xml->createElement('message', htmlspecialchars($data['message']));
|
||||||
$static->appendChild($messageEl);
|
$static->appendChild($messageEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Books
|
// Books
|
||||||
if (isset($data['books']) && is_array($data['books'])) {
|
if (isset($data['books']) && is_array($data['books'])) {
|
||||||
$booksNode = $xml->createElement('books');
|
$booksNode = $xml->createElement('books');
|
||||||
$root->appendChild($booksNode);
|
$root->appendChild($booksNode);
|
||||||
|
|
||||||
foreach ($data['books'] as $book) {
|
foreach ($data['books'] as $book) {
|
||||||
$bookNode = $xml->createElement('book');
|
$bookNode = $xml->createElement('book');
|
||||||
$booksNode->appendChild($bookNode);
|
$booksNode->appendChild($bookNode);
|
||||||
|
|
||||||
foreach (['authorname', 'year', 'title', 'signature'] as $field) {
|
foreach (['authorname', 'year', 'title', 'signature'] as $field) {
|
||||||
$value = isset($book[$field]) ? htmlspecialchars($book[$field]) : '';
|
$value = isset($book[$field]) ? htmlspecialchars($book[$field]) : '';
|
||||||
$fieldNode = $xml->createElement($field, $value);
|
$fieldNode = $xml->createElement($field, $value);
|
||||||
@@ -57,59 +81,69 @@ function generateXML($data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $xml->saveXML();
|
return $xml->saveXML();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate XML for ELSA form
|
* Generate XML for ELSA form
|
||||||
*/
|
*/
|
||||||
function generateELSAXML($data) {
|
function generateELSAXML($data)
|
||||||
|
{
|
||||||
$xml = new DOMDocument('1.0', 'UTF-8');
|
$xml = new DOMDocument('1.0', 'UTF-8');
|
||||||
$xml->formatOutput = true;
|
$xml->formatOutput = true;
|
||||||
|
|
||||||
$root = $xml->createElement('elsa_submission');
|
$root = $xml->createElement('elsa_submission');
|
||||||
$xml->appendChild($root);
|
$xml->appendChild($root);
|
||||||
|
|
||||||
// General info
|
// General info
|
||||||
$generalInfo = $xml->createElement('general_info');
|
$generalInfo = $xml->createElement('general_info');
|
||||||
$root->appendChild($generalInfo);
|
$root->appendChild($generalInfo);
|
||||||
|
|
||||||
$generalFields = ['name', 'lastname', 'title', 'mail', 'subject', 'classname',
|
$generalFields = [
|
||||||
'usage_date_from', 'usage_date_to', 'availability_date'];
|
'name',
|
||||||
|
'lastname',
|
||||||
|
'title',
|
||||||
|
'mail',
|
||||||
|
'subject',
|
||||||
|
'classname',
|
||||||
|
'usage_date_from',
|
||||||
|
'usage_date_to',
|
||||||
|
'availability_date'
|
||||||
|
];
|
||||||
|
|
||||||
foreach ($generalFields as $field) {
|
foreach ($generalFields as $field) {
|
||||||
if (isset($data[$field])) {
|
if (isset($data[$field])) {
|
||||||
$element = $xml->createElement($field, htmlspecialchars($data[$field]));
|
$element = $xml->createElement($field, htmlspecialchars($data[$field]));
|
||||||
$generalInfo->appendChild($element);
|
$generalInfo->appendChild($element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($data['message'])) {
|
if (!empty($data['message'])) {
|
||||||
$messageEl = $xml->createElement('message', htmlspecialchars($data['message']));
|
$messageEl = $xml->createElement('message', htmlspecialchars($data['message']));
|
||||||
$generalInfo->appendChild($messageEl);
|
$generalInfo->appendChild($messageEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Media sections
|
// Media sections
|
||||||
$mediaRoot = $xml->createElement('media');
|
$mediaRoot = $xml->createElement('media');
|
||||||
$root->appendChild($mediaRoot);
|
$root->appendChild($mediaRoot);
|
||||||
|
|
||||||
// Add different media types (monografie, zeitschrift, herausgeber)
|
// Add different media types (monografie, zeitschrift, herausgeber)
|
||||||
$mediaTypes = [
|
$mediaTypes = [
|
||||||
'monografien' => $data['monografien'] ?? [],
|
'monografien' => $data['monografien'] ?? [],
|
||||||
'zeitschriftenartikel' => $data['zeitschriftenartikel'] ?? [],
|
'zeitschriftenartikel' => $data['zeitschriftenartikel'] ?? [],
|
||||||
'herausgeberwerke' => $data['herausgeberwerke'] ?? []
|
'herausgeberwerke' => $data['herausgeberwerke'] ?? []
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($mediaTypes as $type => $entries) {
|
foreach ($mediaTypes as $type => $entries) {
|
||||||
if (!empty($entries)) {
|
if (!empty($entries)) {
|
||||||
$section = $xml->createElement($type);
|
$section = $xml->createElement($type);
|
||||||
$mediaRoot->appendChild($section);
|
$mediaRoot->appendChild($section);
|
||||||
|
|
||||||
foreach ($entries as $entry) {
|
foreach ($entries as $entry) {
|
||||||
$entryNode = $xml->createElement('entry');
|
$entryNode = $xml->createElement('entry');
|
||||||
$section->appendChild($entryNode);
|
$section->appendChild($entryNode);
|
||||||
|
|
||||||
foreach ($entry as $key => $value) {
|
foreach ($entry as $key => $value) {
|
||||||
$fieldNode = $xml->createElement($key, htmlspecialchars($value));
|
$fieldNode = $xml->createElement($key, htmlspecialchars($value));
|
||||||
$entryNode->appendChild($fieldNode);
|
$entryNode->appendChild($fieldNode);
|
||||||
@@ -117,7 +151,7 @@ function generateELSAXML($data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $xml->saveXML();
|
return $xml->saveXML();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,71 +159,251 @@ function generateELSAXML($data) {
|
|||||||
* Send email with XML attachment
|
* Send email with XML attachment
|
||||||
* Uses PHP's mail() function or SMTP if configured
|
* Uses PHP's mail() function or SMTP if configured
|
||||||
*/
|
*/
|
||||||
function sendEmail($subject, $xmlContent, $toEmail = null) {
|
function sendEmail($subject, $xmlContent, $toEmail = null)
|
||||||
|
{
|
||||||
$to = $toEmail ?? MAIL_TO;
|
$to = $toEmail ?? MAIL_TO;
|
||||||
$from = MAIL_FROM;
|
$from = MAIL_FROM;
|
||||||
|
|
||||||
|
writeLog("==========================================================");
|
||||||
|
writeLog("Email Send Attempt");
|
||||||
|
writeLog("From: {$from}");
|
||||||
|
writeLog("To: {$to}");
|
||||||
|
writeLog("Subject: {$subject}");
|
||||||
|
writeLog("Content Length: " . strlen($xmlContent) . " bytes");
|
||||||
|
|
||||||
if (!MAIL_ENABLED) {
|
if (!MAIL_ENABLED) {
|
||||||
// Log instead of sending
|
writeLog("MAIL SENDING DISABLED - Email not sent", 'WARNING');
|
||||||
error_log("==========================================================");
|
writeLog("XML Content:\n" . $xmlContent);
|
||||||
error_log("MAIL SENDING DISABLED - Would have sent:");
|
writeLog("==========================================================");
|
||||||
error_log("From: " . $from);
|
|
||||||
error_log("To: " . $to);
|
|
||||||
error_log("Subject: " . $subject);
|
|
||||||
error_log("----------------------------------------------------------");
|
|
||||||
error_log($xmlContent);
|
|
||||||
error_log("==========================================================");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try using SMTP if credentials are configured
|
// Try using SMTP if credentials are configured
|
||||||
if (SMTP_USERNAME && SMTP_PASSWORD && class_exists('PHPMailer\PHPMailer\PHPMailer')) {
|
if (SMTP_USERNAME && SMTP_PASSWORD) {
|
||||||
return sendEmailSMTP($subject, $xmlContent, $to, $from);
|
writeLog("SMTP credentials configured, attempting SMTP send");
|
||||||
|
$result = sendEmailSMTP($subject, $xmlContent, $to, $from);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
writeLog("Email sent successfully via SMTP", 'SUCCESS');
|
||||||
|
} else {
|
||||||
|
writeLog("Email sending via SMTP failed", 'ERROR');
|
||||||
|
}
|
||||||
|
|
||||||
|
writeLog("==========================================================");
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to PHP mail()
|
// Fallback to PHP mail() only if no SMTP credentials
|
||||||
|
writeLog("No SMTP credentials configured, using PHP mail() function");
|
||||||
$headers = "From: " . $from . "\r\n";
|
$headers = "From: " . $from . "\r\n";
|
||||||
$headers .= "Content-Type: application/xml; charset=UTF-8\r\n";
|
$headers .= "Content-Type: application/xml; charset=UTF-8\r\n";
|
||||||
$headers .= "X-Mailer: PHP/" . phpversion();
|
$headers .= "X-Mailer: PHP/" . phpversion();
|
||||||
|
|
||||||
return mail($to, $subject, $xmlContent, $headers);
|
$result = mail($to, $subject, $xmlContent, $headers);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
writeLog("Email sent successfully via mail()", 'SUCCESS');
|
||||||
|
} else {
|
||||||
|
writeLog("Email sending via mail() failed", 'ERROR');
|
||||||
|
}
|
||||||
|
|
||||||
|
writeLog("==========================================================");
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send email via SMTP using PHPMailer (if available)
|
* Send email via SMTP using PHPMailer (if available) or native PHP sockets
|
||||||
*/
|
*/
|
||||||
function sendEmailSMTP($subject, $xmlContent, $to, $from) {
|
function sendEmailSMTP($subject, $xmlContent, $to, $from)
|
||||||
if (!class_exists('PHPMailer\PHPMailer\PHPMailer')) {
|
{
|
||||||
error_log("PHPMailer not available, falling back to mail()");
|
// Try PHPMailer first if available
|
||||||
|
if (class_exists('PHPMailer\PHPMailer\PHPMailer')) {
|
||||||
|
writeLog("Initializing PHPMailer for SMTP send");
|
||||||
|
writeLog("SMTP Host: " . SMTP_HOST . ":" . SMTP_PORT);
|
||||||
|
writeLog("SMTP Encryption: " . SMTP_ENCRYPTION);
|
||||||
|
writeLog("SMTP Username: " . SMTP_USERNAME);
|
||||||
|
|
||||||
|
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Server settings
|
||||||
|
$mail->isSMTP();
|
||||||
|
$mail->Host = SMTP_HOST;
|
||||||
|
$mail->SMTPAuth = true;
|
||||||
|
$mail->Username = SMTP_USERNAME;
|
||||||
|
$mail->Password = SMTP_PASSWORD;
|
||||||
|
$mail->SMTPSecure = SMTP_ENCRYPTION;
|
||||||
|
$mail->Port = SMTP_PORT;
|
||||||
|
$mail->CharSet = 'UTF-8';
|
||||||
|
|
||||||
|
writeLog("SMTP connection configured");
|
||||||
|
|
||||||
|
// Recipients
|
||||||
|
$mail->setFrom($from);
|
||||||
|
$mail->addAddress($to);
|
||||||
|
|
||||||
|
writeLog("Recipients configured");
|
||||||
|
|
||||||
|
// Content - XML as body
|
||||||
|
$mail->isHTML(false);
|
||||||
|
$mail->Subject = $subject;
|
||||||
|
$mail->Body = $xmlContent;
|
||||||
|
$mail->ContentType = 'text/plain';
|
||||||
|
|
||||||
|
writeLog("Sending email via SMTP...");
|
||||||
|
$mail->send();
|
||||||
|
|
||||||
|
writeLog("SMTP send() completed successfully", 'SUCCESS');
|
||||||
|
return true;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
writeLog("SMTP Exception: " . $e->getMessage(), 'ERROR');
|
||||||
|
writeLog("PHPMailer ErrorInfo: " . $mail->ErrorInfo, 'ERROR');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to read SMTP multi-line response
|
||||||
|
$readResponse = function ($socket) {
|
||||||
|
$response = '';
|
||||||
|
while ($line = fgets($socket, 515)) {
|
||||||
|
$response .= $line;
|
||||||
|
// Check if this is the last line (code followed by space, not hyphen)
|
||||||
|
if (preg_match('/^\d{3} /', $line)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $response;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fallback to native PHP SMTP
|
||||||
|
writeLog("PHPMailer not available, using native PHP SMTP implementation");
|
||||||
|
writeLog("SMTP Host: " . SMTP_HOST . ":" . SMTP_PORT);
|
||||||
|
writeLog("SMTP Encryption: " . SMTP_ENCRYPTION);
|
||||||
|
|
||||||
|
// Check if required transports are available
|
||||||
|
$transports = stream_get_transports();
|
||||||
|
writeLog("Available transports: " . implode(', ', $transports));
|
||||||
|
|
||||||
|
if (SMTP_ENCRYPTION === 'ssl' && !in_array('ssl', $transports)) {
|
||||||
|
writeLog("SSL transport not available. Enable OpenSSL extension in PHP.", 'ERROR');
|
||||||
|
writeLog("Try changing SMTP_ENCRYPTION to 'tls' and SMTP_PORT to 587 in config.php", 'ERROR');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Server settings
|
// Build the connection string - always start with plain TCP for TLS
|
||||||
$mail->isSMTP();
|
if (SMTP_ENCRYPTION === 'ssl') {
|
||||||
$mail->Host = SMTP_HOST;
|
$host = 'ssl://' . SMTP_HOST;
|
||||||
$mail->SMTPAuth = true;
|
} else {
|
||||||
$mail->Username = SMTP_USERNAME;
|
$host = SMTP_HOST;
|
||||||
$mail->Password = SMTP_PASSWORD;
|
}
|
||||||
$mail->SMTPSecure = SMTP_ENCRYPTION;
|
$timeout = 30;
|
||||||
$mail->Port = SMTP_PORT;
|
|
||||||
$mail->CharSet = 'UTF-8';
|
writeLog("Connecting to {$host}:" . SMTP_PORT);
|
||||||
|
$smtp = @fsockopen($host, SMTP_PORT, $errno, $errstr, $timeout);
|
||||||
// Recipients
|
|
||||||
$mail->setFrom($from);
|
if (!$smtp) {
|
||||||
$mail->addAddress($to);
|
writeLog("Failed to connect: ({$errno}) {$errstr}", 'ERROR');
|
||||||
|
return false;
|
||||||
// Content
|
}
|
||||||
$mail->Subject = $subject;
|
|
||||||
$mail->Body = $xmlContent;
|
writeLog("Connected successfully");
|
||||||
$mail->ContentType = 'application/xml';
|
|
||||||
|
// Read server response
|
||||||
$mail->send();
|
$response = $readResponse($smtp);
|
||||||
return true;
|
writeLog("Server greeting: " . trim($response));
|
||||||
|
|
||||||
|
// Send EHLO
|
||||||
|
fputs($smtp, "EHLO " . SMTP_HOST . "\r\n");
|
||||||
|
$response = $readResponse($smtp);
|
||||||
|
writeLog("EHLO response: " . trim(str_replace("\r\n", " | ", $response)));
|
||||||
|
|
||||||
|
// Start TLS if needed and not using SSL
|
||||||
|
if (SMTP_ENCRYPTION === 'tls') {
|
||||||
|
fputs($smtp, "STARTTLS\r\n");
|
||||||
|
$response = $readResponse($smtp);
|
||||||
|
writeLog("STARTTLS response: " . trim($response));
|
||||||
|
|
||||||
|
if (strpos($response, '220') === 0) {
|
||||||
|
if (in_array('tls', $transports) || in_array('ssl', $transports)) {
|
||||||
|
$crypto = @stream_socket_enable_crypto($smtp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
|
||||||
|
if ($crypto) {
|
||||||
|
writeLog("TLS encryption enabled successfully");
|
||||||
|
fputs($smtp, "EHLO " . SMTP_HOST . "\r\n");
|
||||||
|
$response = $readResponse($smtp);
|
||||||
|
writeLog("EHLO after TLS: " . trim(str_replace("\r\n", " | ", $response)));
|
||||||
|
} else {
|
||||||
|
writeLog("Failed to enable TLS encryption", 'WARNING');
|
||||||
|
writeLog("Continuing without encryption (not recommended)", 'WARNING');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
writeLog("TLS/SSL transports not available. Enable OpenSSL extension.", 'WARNING');
|
||||||
|
writeLog("Continuing without encryption (not recommended)", 'WARNING');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticate
|
||||||
|
fputs($smtp, "AUTH LOGIN\r\n");
|
||||||
|
$response = $readResponse($smtp);
|
||||||
|
writeLog("AUTH response: " . trim($response));
|
||||||
|
|
||||||
|
fputs($smtp, base64_encode(SMTP_USERNAME) . "\r\n");
|
||||||
|
$response = $readResponse($smtp);
|
||||||
|
|
||||||
|
fputs($smtp, base64_encode(SMTP_PASSWORD) . "\r\n");
|
||||||
|
$response = $readResponse($smtp);
|
||||||
|
|
||||||
|
if (strpos($response, '235') !== 0) {
|
||||||
|
writeLog("Authentication failed: " . trim($response), 'ERROR');
|
||||||
|
fclose($smtp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeLog("Authentication successful");
|
||||||
|
|
||||||
|
// Send MAIL FROM
|
||||||
|
fputs($smtp, "MAIL FROM: <{$from}>\r\n");
|
||||||
|
$response = $readResponse($smtp);
|
||||||
|
writeLog("MAIL FROM response: " . trim($response));
|
||||||
|
|
||||||
|
// Send RCPT TO
|
||||||
|
fputs($smtp, "RCPT TO: <{$to}>\r\n");
|
||||||
|
$response = $readResponse($smtp);
|
||||||
|
writeLog("RCPT TO response: " . trim($response));
|
||||||
|
|
||||||
|
// Send DATA
|
||||||
|
fputs($smtp, "DATA\r\n");
|
||||||
|
$response = $readResponse($smtp);
|
||||||
|
writeLog("DATA response: " . trim($response));
|
||||||
|
|
||||||
|
// Send email headers and body
|
||||||
|
$headers = "From: {$from}\r\n";
|
||||||
|
$headers .= "To: {$to}\r\n";
|
||||||
|
$headers .= "Subject: {$subject}\r\n";
|
||||||
|
$headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
|
||||||
|
$headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
|
||||||
|
$headers .= "\r\n";
|
||||||
|
|
||||||
|
fputs($smtp, $headers . $xmlContent . "\r\n.\r\n");
|
||||||
|
$response = $readResponse($smtp);
|
||||||
|
writeLog("Message response: " . trim($response));
|
||||||
|
|
||||||
|
// Quit
|
||||||
|
fputs($smtp, "QUIT\r\n");
|
||||||
|
$readResponse($smtp); // Read QUIT response
|
||||||
|
fclose($smtp);
|
||||||
|
|
||||||
|
if (strpos($response, '250') === 0) {
|
||||||
|
writeLog("Email sent successfully via native SMTP", 'SUCCESS');
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
writeLog("Email sending failed: " . trim($response), 'ERROR');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
error_log("Email sending failed: " . $mail->ErrorInfo);
|
writeLog("Native SMTP Exception: " . $e->getMessage(), 'ERROR');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,7 +411,8 @@ function sendEmailSMTP($subject, $xmlContent, $to, $from) {
|
|||||||
/**
|
/**
|
||||||
* Redirect to URL
|
* Redirect to URL
|
||||||
*/
|
*/
|
||||||
function redirect($url) {
|
function redirect($url)
|
||||||
|
{
|
||||||
header("Location: " . $url);
|
header("Location: " . $url);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@@ -205,14 +420,16 @@ function redirect($url) {
|
|||||||
/**
|
/**
|
||||||
* Get POST value with default
|
* Get POST value with default
|
||||||
*/
|
*/
|
||||||
function post($key, $default = '') {
|
function post($key, $default = '')
|
||||||
|
{
|
||||||
return isset($_POST[$key]) ? sanitizeInput($_POST[$key]) : $default;
|
return isset($_POST[$key]) ? sanitizeInput($_POST[$key]) : $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all POST values matching a pattern (for arrays)
|
* Get all POST values matching a pattern (for arrays)
|
||||||
*/
|
*/
|
||||||
function postArray($key) {
|
function postArray($key)
|
||||||
return isset($_POST[$key]) && is_array($_POST[$key]) ?
|
{
|
||||||
array_map('sanitizeInput', $_POST[$key]) : [];
|
return isset($_POST[$key]) && is_array($_POST[$key]) ?
|
||||||
|
array_map('sanitizeInput', $_POST[$key]) : [];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user