diff --git a/php/OPENSSL_SETUP.md b/php/OPENSSL_SETUP.md
new file mode 100644
index 0000000..df6e21c
--- /dev/null
+++ b/php/OPENSSL_SETUP.md
@@ -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
diff --git a/php/README.md b/php/README.md
index 54126cb..84a0bb2 100644
--- a/php/README.md
+++ b/php/README.md
@@ -95,13 +95,61 @@
- Set environment variables through hosting control panel
- 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
### Emails not sending
1. Check `MAIL_ENABLED` is set to `true`
-2. Verify SMTP credentials are correct
-3. Check server error logs: `tail -f /var/log/apache2/error.log`
-4. Test with `MAIL_ENABLED=false` to see XML output in logs
+2. **Check `php/mail.log`** for detailed error messages
+3. Verify SMTP credentials are correct
+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
- Ensure all required fields have values
diff --git a/php/config.php b/php/config.php
index 4db6933..a975136 100644
--- a/php/config.php
+++ b/php/config.php
@@ -11,19 +11,23 @@ error_reporting(E_ALL);
ini_set('display_errors', 1);
// Email configuration
-define('MAIL_ENABLED', 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_PORT', getenv('SMTP_PORT') ?: 465);
-define('SMTP_ENCRYPTION', 'ssl'); // 'ssl' or 'tls' or '' for none
-define('SMTP_USERNAME', getenv('MAIL_USERNAME') ?: '');
-define('SMTP_PASSWORD', getenv('MAIL_PASSWORD') ?: '');
-define('MAIL_FROM', getenv('MAIL_FROM') ?: 'alexander.kirchner@ph-freiburg.de');
-define('MAIL_TO', getenv('MAIL_TO') ?: 'semesterapparate@ph-freiburg.de');
+define('MAIL_ENABLED', true);//getenv('MAIL_ENABLED') !== false ? filter_var(getenv('MAIL_ENABLED'), FILTER_VALIDATE_BOOLEAN) : true);
+define('SMTP_HOST', 'smtp.ph-freiburg.de');//getenv('SMTP_HOST') ?: 'smtp.ph-freiburg.de');
+define('SMTP_PORT', 587);//getenv('SMTP_PORT') ?: 587); // Use 587 for TLS, 465 for SSL
+define('SMTP_ENCRYPTION', 'tls'); // 'ssl' or 'tls' or '' for none
+define('SMTP_USERNAME', 'aky547');//getenv('MAIL_USERNAME') ?: 'aky547');
+define('SMTP_PASSWORD', 'CMcDna3qPh2*n');//getenv('MAIL_PASSWORD') ?: 'CMcDna3qPh2*n');
+define('MAIL_FROM', 'alexander.kirchner@ph-freiburg.de');//getenv('MAIL_FROM') ?: 'alexander.kirchner@ph-freiburg.de');
+define('MAIL_TO', 'kirchneralexander020@gmail.com');//getenv('MAIL_TO') ?: 'kirchneralexander@proton.me');
// Application settings
define('BASE_PATH', __DIR__);
define('STATIC_PATH', '/static');
+// Logging configuration
+define('LOG_FILE', BASE_PATH . '/mail.log');
+define('LOG_ENABLED', true);
+
// Signature validation API (optional Python service)
define('SIGNATURE_API_URL', getenv('SIGNATURE_API_URL') ?: 'http://localhost:8001');
diff --git a/php/elsa.php b/php/elsa.php
index b70b41b..0601f87 100644
--- a/php/elsa.php
+++ b/php/elsa.php
@@ -302,8 +302,8 @@
'
| ' +
' | ' +
' | ' +
- attachSignatureListeners(row);
' | ';
+ attachSignatureListeners(row);
}
}
@@ -491,7 +491,9 @@
function removeMediaSection(sectionId) {
const section = document.getElementById(sectionId);
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 => {
const signatureInput = row.querySelector('input[name*="_signature"]');
if (signatureInput) {
@@ -504,9 +506,7 @@
btn.disabled = false;
btn.title = 'Sektion hinzufügen';
}
- updateSubmitButton(); btn.disabled = false;
- btn.title = 'Sektion hinzufügen';
- }
+ updateSubmitButton();
}
}
}
diff --git a/php/functions.php b/php/functions.php
index aad384d..cd1cc4c 100644
--- a/php/functions.php
+++ b/php/functions.php
@@ -1,55 +1,79 @@
formatOutput = true;
-
+
$root = $xml->createElement('form_submission');
$xml->appendChild($root);
-
+
// Static data
$static = $xml->createElement('static');
$root->appendChild($static);
-
+
foreach (['name', 'lastname', 'title', 'telno', 'mail', 'apparatsname', 'subject', 'semester', 'dauerapparat'] as $field) {
if (isset($data[$field])) {
$element = $xml->createElement($field, htmlspecialchars($data[$field]));
$static->appendChild($element);
}
}
-
+
if (!empty($data['message'])) {
$messageEl = $xml->createElement('message', htmlspecialchars($data['message']));
$static->appendChild($messageEl);
}
-
+
// Books
if (isset($data['books']) && is_array($data['books'])) {
$booksNode = $xml->createElement('books');
$root->appendChild($booksNode);
-
+
foreach ($data['books'] as $book) {
$bookNode = $xml->createElement('book');
$booksNode->appendChild($bookNode);
-
+
foreach (['authorname', 'year', 'title', 'signature'] as $field) {
$value = isset($book[$field]) ? htmlspecialchars($book[$field]) : '';
$fieldNode = $xml->createElement($field, $value);
@@ -57,59 +81,69 @@ function generateXML($data) {
}
}
}
-
+
return $xml->saveXML();
}
/**
* Generate XML for ELSA form
*/
-function generateELSAXML($data) {
+function generateELSAXML($data)
+{
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->formatOutput = true;
-
+
$root = $xml->createElement('elsa_submission');
$xml->appendChild($root);
-
+
// General info
$generalInfo = $xml->createElement('general_info');
$root->appendChild($generalInfo);
-
- $generalFields = ['name', 'lastname', 'title', 'mail', 'subject', 'classname',
- 'usage_date_from', 'usage_date_to', 'availability_date'];
-
+
+ $generalFields = [
+ 'name',
+ 'lastname',
+ 'title',
+ 'mail',
+ 'subject',
+ 'classname',
+ 'usage_date_from',
+ 'usage_date_to',
+ 'availability_date'
+ ];
+
foreach ($generalFields as $field) {
if (isset($data[$field])) {
$element = $xml->createElement($field, htmlspecialchars($data[$field]));
$generalInfo->appendChild($element);
}
}
-
+
if (!empty($data['message'])) {
$messageEl = $xml->createElement('message', htmlspecialchars($data['message']));
$generalInfo->appendChild($messageEl);
}
-
+
// Media sections
$mediaRoot = $xml->createElement('media');
$root->appendChild($mediaRoot);
-
+
// Add different media types (monografie, zeitschrift, herausgeber)
$mediaTypes = [
'monografien' => $data['monografien'] ?? [],
'zeitschriftenartikel' => $data['zeitschriftenartikel'] ?? [],
'herausgeberwerke' => $data['herausgeberwerke'] ?? []
];
-
+
foreach ($mediaTypes as $type => $entries) {
if (!empty($entries)) {
$section = $xml->createElement($type);
$mediaRoot->appendChild($section);
-
+
foreach ($entries as $entry) {
$entryNode = $xml->createElement('entry');
$section->appendChild($entryNode);
-
+
foreach ($entry as $key => $value) {
$fieldNode = $xml->createElement($key, htmlspecialchars($value));
$entryNode->appendChild($fieldNode);
@@ -117,7 +151,7 @@ function generateELSAXML($data) {
}
}
}
-
+
return $xml->saveXML();
}
@@ -125,71 +159,251 @@ function generateELSAXML($data) {
* Send email with XML attachment
* 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;
$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) {
- // Log instead of sending
- error_log("==========================================================");
- error_log("MAIL SENDING DISABLED - Would have sent:");
- error_log("From: " . $from);
- error_log("To: " . $to);
- error_log("Subject: " . $subject);
- error_log("----------------------------------------------------------");
- error_log($xmlContent);
- error_log("==========================================================");
+ writeLog("MAIL SENDING DISABLED - Email not sent", 'WARNING');
+ writeLog("XML Content:\n" . $xmlContent);
+ writeLog("==========================================================");
return true;
}
-
+
// Try using SMTP if credentials are configured
- if (SMTP_USERNAME && SMTP_PASSWORD && class_exists('PHPMailer\PHPMailer\PHPMailer')) {
- return sendEmailSMTP($subject, $xmlContent, $to, $from);
+ if (SMTP_USERNAME && SMTP_PASSWORD) {
+ 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 .= "Content-Type: application/xml; charset=UTF-8\r\n";
$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) {
- if (!class_exists('PHPMailer\PHPMailer\PHPMailer')) {
- error_log("PHPMailer not available, falling back to mail()");
+function sendEmailSMTP($subject, $xmlContent, $to, $from)
+{
+ // 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;
}
-
- $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';
-
- // Recipients
- $mail->setFrom($from);
- $mail->addAddress($to);
-
- // Content
- $mail->Subject = $subject;
- $mail->Body = $xmlContent;
- $mail->ContentType = 'application/xml';
-
- $mail->send();
- return true;
+ // Build the connection string - always start with plain TCP for TLS
+ if (SMTP_ENCRYPTION === 'ssl') {
+ $host = 'ssl://' . SMTP_HOST;
+ } else {
+ $host = SMTP_HOST;
+ }
+ $timeout = 30;
+
+ writeLog("Connecting to {$host}:" . SMTP_PORT);
+ $smtp = @fsockopen($host, SMTP_PORT, $errno, $errstr, $timeout);
+
+ if (!$smtp) {
+ writeLog("Failed to connect: ({$errno}) {$errstr}", 'ERROR');
+ return false;
+ }
+
+ writeLog("Connected successfully");
+
+ // Read server response
+ $response = $readResponse($smtp);
+ 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) {
- error_log("Email sending failed: " . $mail->ErrorInfo);
+ writeLog("Native SMTP Exception: " . $e->getMessage(), 'ERROR');
return false;
}
}
@@ -197,7 +411,8 @@ function sendEmailSMTP($subject, $xmlContent, $to, $from) {
/**
* Redirect to URL
*/
-function redirect($url) {
+function redirect($url)
+{
header("Location: " . $url);
exit;
}
@@ -205,14 +420,16 @@ function redirect($url) {
/**
* Get POST value with default
*/
-function post($key, $default = '') {
+function post($key, $default = '')
+{
return isset($_POST[$key]) ? sanitizeInput($_POST[$key]) : $default;
}
/**
* Get all POST values matching a pattern (for arrays)
*/
-function postArray($key) {
- return isset($_POST[$key]) && is_array($_POST[$key]) ?
- array_map('sanitizeInput', $_POST[$key]) : [];
+function postArray($key)
+{
+ return isset($_POST[$key]) && is_array($_POST[$key]) ?
+ array_map('sanitizeInput', $_POST[$key]) : [];
}