From 6bb30a6de2f0e450aaa87df533419b5411657e42 Mon Sep 17 00:00:00 2001 From: "cto-new[bot]" <140088366+cto-new[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 12:28:30 +0000 Subject: [PATCH] Add OpenSMTPD support for email server functionality --- Dockerfile | 45 ++++++++++++++++++++++++++++++++++++- docker-compose.yml | 4 ++++ scripts/entrypoint.sh | 51 ++++++++++++++++++++++++++++++++++++++++++ scripts/healthcheck.sh | 36 +++++++++++++++++++++++++++++ stack-portainer.yml | 4 ++++ 5 files changed, 139 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b02dc37..59f9baa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,7 @@ ENV DEBIAN_FRONTEND=noninteractive \ LC_ALL=C.UTF-8 # Install minimal system dependencies only (no PowerShell or Node.js from apt) +# Includes OpenSMTPD dependencies for email server functionality RUN apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates \ @@ -37,6 +38,11 @@ RUN apt-get update \ php-zip \ php-gd \ php-curl \ + opensmtpd \ + opensmtpd-extras \ + libevent-dev \ + libasr-dev \ + ca-certificates \ && rm -rf /var/lib/apt/lists/* # Install PowerShell 7.x from official binary release (architecture-aware) @@ -113,6 +119,40 @@ RUN cd /opt/webchat && npm install --production && chmod -R 755 /opt/webchat COPY chat_v2 /opt/webchat_v2 RUN chmod -R 755 /opt/webchat_v2 +# Create OpenSMTPD expected directory structure for application compatibility +# The application expects OpenSMTPD at /workspace/src/backend/app/opensmtpd/install/ +RUN mkdir -p /workspace/src/backend/app/opensmtpd/install/etc \ + && mkdir -p /workspace/src/backend/app/opensmtpd/install/var/spool/smtpd \ + && mkdir -p /workspace/src/backend/app/opensmtpd/install/var/spool/queue \ + && mkdir -p /workspace/src/backend/app/opensmtpd/install/var/run \ + && ln -sf /usr/sbin/smtpd /workspace/src/backend/app/opensmtpd/install/sbin/smtpd \ + && ln -sf /usr/sbin/smtpctl /workspace/src/backend/app/opensmtpd/install/sbin/smtpctl \ + && ln -sf /usr/bin/sendmail /workspace/src/backend/app/opensmtpd/install/sbin/sendmail \ + && ln -sf /etc/ssl/certs /workspace/src/backend/app/opensmtpd/install/etc/certs \ + && chmod -R 755 /workspace/src/backend/app/opensmtpd/install + +# Create OpenSMTPD configuration +RUN echo 'pki plugincompass.com cert "/workspace/src/backend/app/opensmtpd/install/etc/certs/fullchain.pem"' > /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'pki plugincompass.com key "/workspace/src/backend/app/opensmtpd/install/etc/certs/privkey.pem"' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo '' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'table domains file:/workspace/src/backend/app/opensmtpd/install/etc/domains' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'table aliases file:/workspace/src/backend/app/opensmtpd/install/etc/aliases' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo '' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'listen on 0.0.0.0 port 25' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'listen on 0.0.0.0 port 587 tls-require pki plugincompass.com' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'listen on 0.0.0.0 port 465 smtps pki plugincompass.com' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo '' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'action "local" mbox alias ' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'action "relay" relay' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo '' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'match from any for domain action "local"' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'match for local action "local"' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'match auth from any for any action "relay"' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && echo 'match from local for any action "relay"' >> /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf \ + && touch /workspace/src/backend/app/opensmtpd/install/etc/domains \ + && touch /workspace/src/backend/app/opensmtpd/install/etc/aliases \ + && chmod 644 /workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf + # Create workspace directory and set as workdir so pwsh starts where repo/workspace is mounted RUN mkdir -p /home/web/data \ && mkdir -p /var/log/shopify-ai \ @@ -121,7 +161,10 @@ WORKDIR /home/web/data # Container defaults - Shopify AI App Builder # Port 4500: Web UI (chat/builder interface) -EXPOSE 4500 +# Port 25: SMTP (OpenSMTPD) +# Port 587: SMTP submission (OpenSMTPD) +# Port 465: SMTPS (OpenSMTPD) +EXPOSE 4500 25 587 465 HEALTHCHECK --interval=30s --timeout=15s --start-period=60s --retries=5 \ CMD /usr/local/bin/healthcheck.sh || exit 1 diff --git a/docker-compose.yml b/docker-compose.yml index 4feb5db..2132808 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,10 @@ services: build: . ports: - "4500:4500" + # OpenSMTPD ports for email functionality + - "25:25" + - "587:587" + - "465:465" restart: unless-stopped environment: - OPENCODE_API_KEY=${OPENCODE_API_KEY:-} diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index b4cbb72..c9803ae 100755 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -166,6 +166,49 @@ else mkdir -p "$REPO_DIR" fi +log "Setting up OpenSMTPD service..." + +# Start OpenSMTPD if configuration exists +OPENSMTPD_CONFIG="/workspace/src/backend/app/opensmtpd/install/etc/smtpd.conf" +OPENSMTPD_PID_FILE="/workspace/src/backend/app/opensmtpd/install/var/run/smtpd.pid" +OPENSMTPD_BINARY="/workspace/src/backend/app/opensmtpd/install/sbin/smtpd" + +if [ -f "$OPENSMTPD_CONFIG" ] && [ -x "$OPENSMTPD_BINARY" ]; then + log "OpenSMTPD configuration found at $OPENSMTPD_CONFIG" + + # Ensure required directories exist with proper permissions + mkdir -p /workspace/src/backend/app/opensmtpd/install/var/spool/smtpd + mkdir -p /workspace/src/backend/app/opensmtpd/install/var/spool/queue + mkdir -p /workspace/src/backend/app/opensmtpd/install/var/run + chmod -R 755 /workspace/src/backend/app/opensmtpd/install/var + + # Check if OpenSMTPD is already running + if [ -f "$OPENSMTPD_PID_FILE" ] && kill -0 "$(cat "$OPENSMTPD_PID_FILE")" 2>/dev/null; then + log "OpenSMTPD is already running (PID: $(cat "$OPENSMTPD_PID_FILE"))" + else + log "Starting OpenSMTPD..." + "$OPENSMTPD_BINARY" -d -f "$OPENSMTPD_CONFIG" 2>&1 & + OPENSMTPD_PID=$! + + # Wait for OpenSMTPD to start + sleep 2 + if kill -0 "$OPENSMTPD_PID" 2>/dev/null; then + log "OpenSMTPD started successfully (PID: $OPENSMTPD_PID)" + echo "$OPENSMTPD_PID" > "$OPENSMTPD_PID_FILE" + else + log "WARNING: OpenSMTPD failed to start" + fi + fi +else + log "OpenSMTPD not configured or binary not found, skipping SMTP setup" + if [ ! -f "$OPENSMTPD_CONFIG" ]; then + log " Config file missing: $OPENSMTPD_CONFIG" + fi + if [ ! -x "$OPENSMTPD_BINARY" ]; then + log " Binary not executable: $OPENSMTPD_BINARY" + fi +fi + log "Starting Shopify AI App Builder service..." # Use /opt/webchat directly as it contains the actual server.js with node_modules @@ -283,6 +326,14 @@ cleanup() { monitor_resources fi + # Stop OpenSMTPD if running + if [ -n "$OPENSMTPD_PID" ] && kill -0 "$OPENSMTPD_PID" 2>/dev/null; then + log "Terminating OpenSMTPD service (PID: $OPENSMTPD_PID)" + kill "$OPENSMTPD_PID" 2>/dev/null || true + wait "$OPENSMTPD_PID" 2>/dev/null || true + log "OpenSMTPD service terminated" + fi + if [ -n "$MONITOR_PID" ] && kill -0 "$MONITOR_PID" 2>/dev/null; then log "Terminating monitor process (PID: $MONITOR_PID)" kill "$MONITOR_PID" 2>/dev/null || true diff --git a/scripts/healthcheck.sh b/scripts/healthcheck.sh index 7fbb2b2..c2f1a92 100644 --- a/scripts/healthcheck.sh +++ b/scripts/healthcheck.sh @@ -172,6 +172,42 @@ main() { exit_code=1 fi + # Check OpenSMTPD service (ports 25, 587, 465) + health_log "INFO" "=== OpenSMTPD Service ===" + OPENSMTPD_BINARY="/workspace/src/backend/app/opensmtpd/install/sbin/smtpd" + if [ -x "$OPENSMTPD_BINARY" ]; then + # Check SMTP port 25 + if check_port 25 "SMTP"; then + health_log "INFO" "✓ SMTP port 25 is listening" + else + health_log "WARN" "⚠ SMTP port 25 is not listening (may be normal if not using inbound email)" + fi + + # Check SMTP submission port 587 + if check_port 587 "SMTP Submission"; then + health_log "INFO" "✓ SMTP submission port 587 is listening" + else + health_log "WARN" "⚠ SMTP submission port 587 is not listening" + fi + + # Check SMTPS port 465 + if check_port 465 "SMTPS"; then + health_log "INFO" "✓ SMTPS port 465 is listening" + else + health_log "WARN" "⚠ SMTPS port 465 is not listening" + fi + + # Check OpenSMTPD process + if pgrep -f "smtpd" > /dev/null; then + local smtpd_pid=$(pgrep -f "smtpd" | head -1) + health_log "INFO" "✓ OpenSMTPD process running (PID: ${smtpd_pid})" + else + health_log "WARN" "⚠ OpenSMTPD process not found (may be disabled)" + fi + else + health_log "INFO" "OpenSMTPD not installed at expected location, skipping SMTP checks" + fi + # ttyd service has been removed, no longer checking port 4501 health_log "INFO" "========== HEALTH CHECK END ===========" diff --git a/stack-portainer.yml b/stack-portainer.yml index 0c30b4f..34b7cbe 100644 --- a/stack-portainer.yml +++ b/stack-portainer.yml @@ -8,6 +8,10 @@ services: # This enables reliable multi-architecture builds (amd64, arm64, etc.) ports: - "4500:4500" + # OpenSMTPD ports for email functionality + - "25:25" + - "587:587" + - "465:465" restart: unless-stopped environment: - OPENCODE_API_KEY=${OPENCODE_API_KEY:-}