dockerize smtp-proxy (#118)
This commit is contained in:
79
.github/workflows/publish.yml
vendored
79
.github/workflows/publish.yml
vendored
@@ -23,6 +23,13 @@ jobs:
|
|||||||
os:
|
os:
|
||||||
- warp-ubuntu-latest-x64-2x
|
- warp-ubuntu-latest-x64-2x
|
||||||
- warp-ubuntu-latest-arm64-2x
|
- warp-ubuntu-latest-arm64-2x
|
||||||
|
app:
|
||||||
|
- name: unsend
|
||||||
|
dockerfile: ./docker/Dockerfile
|
||||||
|
context: .
|
||||||
|
- name: smtp-proxy
|
||||||
|
dockerfile: ./Dockerfile
|
||||||
|
context: ./apps/smtp-server
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -53,23 +60,23 @@ jobs:
|
|||||||
GIT_SHA="$(git rev-parse HEAD)"
|
GIT_SHA="$(git rev-parse HEAD)"
|
||||||
|
|
||||||
docker build \
|
docker build \
|
||||||
-f ./docker/Dockerfile \
|
-f ${{ matrix.app.dockerfile }} \
|
||||||
--progress=plain \
|
--progress=plain \
|
||||||
-t "unsend/unsend-$BUILD_PLATFORM:latest" \
|
-t "unsend/${{ matrix.app.name }}-$BUILD_PLATFORM:latest" \
|
||||||
-t "unsend/unsend-$BUILD_PLATFORM:$GIT_SHA" \
|
-t "unsend/${{ matrix.app.name }}-$BUILD_PLATFORM:$GIT_SHA" \
|
||||||
-t "unsend/unsend-$BUILD_PLATFORM:$APP_VERSION" \
|
-t "unsend/${{ matrix.app.name }}-$BUILD_PLATFORM:$APP_VERSION" \
|
||||||
-t "ghcr.io/unsend-dev/unsend-$BUILD_PLATFORM:latest" \
|
-t "ghcr.io/unsend-dev/${{ matrix.app.name }}-$BUILD_PLATFORM:latest" \
|
||||||
-t "ghcr.io/unsend-dev/unsend-$BUILD_PLATFORM:$GIT_SHA" \
|
-t "ghcr.io/unsend-dev/${{ matrix.app.name }}-$BUILD_PLATFORM:$GIT_SHA" \
|
||||||
-t "ghcr.io/unsend-dev/unsend-$BUILD_PLATFORM:$APP_VERSION" \
|
-t "ghcr.io/unsend-dev/${{ matrix.app.name }}-$BUILD_PLATFORM:$APP_VERSION" \
|
||||||
.
|
${{ matrix.app.context }}
|
||||||
|
|
||||||
- name: Push the docker image to DockerHub
|
- name: Push the docker image to DockerHub
|
||||||
run: docker push --all-tags "unsend/unsend-$BUILD_PLATFORM"
|
run: docker push --all-tags "unsend/${{ matrix.app.name }}-$BUILD_PLATFORM"
|
||||||
env:
|
env:
|
||||||
BUILD_PLATFORM: ${{ matrix.os == 'warp-ubuntu-latest-arm64-2x' && 'arm64' || 'amd64' }}
|
BUILD_PLATFORM: ${{ matrix.os == 'warp-ubuntu-latest-arm64-2x' && 'arm64' || 'amd64' }}
|
||||||
|
|
||||||
- name: Push the docker image to GitHub Container Registry
|
- name: Push the docker image to GitHub Container Registry
|
||||||
run: docker push --all-tags "ghcr.io/unsend-dev/unsend-$BUILD_PLATFORM"
|
run: docker push --all-tags "ghcr.io/unsend-dev/${{ matrix.app.name }}-$BUILD_PLATFORM"
|
||||||
env:
|
env:
|
||||||
BUILD_PLATFORM: ${{ matrix.os == 'warp-ubuntu-latest-arm64-2x' && 'arm64' || 'amd64' }}
|
BUILD_PLATFORM: ${{ matrix.os == 'warp-ubuntu-latest-arm64-2x' && 'arm64' || 'amd64' }}
|
||||||
|
|
||||||
@@ -103,45 +110,49 @@ jobs:
|
|||||||
APP_VERSION="$(git name-rev --tags --name-only $(git rev-parse HEAD) | head -n 1 | sed 's/\^0//')"
|
APP_VERSION="$(git name-rev --tags --name-only $(git rev-parse HEAD) | head -n 1 | sed 's/\^0//')"
|
||||||
GIT_SHA="$(git rev-parse HEAD)"
|
GIT_SHA="$(git rev-parse HEAD)"
|
||||||
|
|
||||||
|
for APP_NAME in unsend smtp-proxy; do
|
||||||
docker manifest create \
|
docker manifest create \
|
||||||
unsend/unsend:latest \
|
unsend/$APP_NAME:latest \
|
||||||
--amend unsend/unsend-amd64:latest \
|
--amend unsend/$APP_NAME-amd64:latest \
|
||||||
--amend unsend/unsend-arm64:latest \
|
--amend unsend/$APP_NAME-arm64:latest
|
||||||
|
|
||||||
docker manifest create \
|
docker manifest create \
|
||||||
unsend/unsend:$GIT_SHA \
|
unsend/$APP_NAME:$GIT_SHA \
|
||||||
--amend unsend/unsend-amd64:$GIT_SHA \
|
--amend unsend/$APP_NAME-amd64:$GIT_SHA \
|
||||||
--amend unsend/unsend-arm64:$GIT_SHA \
|
--amend unsend/$APP_NAME-arm64:$GIT_SHA
|
||||||
|
|
||||||
docker manifest create \
|
docker manifest create \
|
||||||
unsend/unsend:$APP_VERSION \
|
unsend/$APP_NAME:$APP_VERSION \
|
||||||
--amend unsend/unsend-amd64:$APP_VERSION \
|
--amend unsend/$APP_NAME-amd64:$APP_VERSION \
|
||||||
--amend unsend/unsend-arm64:$APP_VERSION \
|
--amend unsend/$APP_NAME-arm64:$APP_VERSION
|
||||||
|
|
||||||
docker manifest push unsend/unsend:latest
|
docker manifest push unsend/$APP_NAME:latest
|
||||||
docker manifest push unsend/unsend:$GIT_SHA
|
docker manifest push unsend/$APP_NAME:$GIT_SHA
|
||||||
docker manifest push unsend/unsend:$APP_VERSION
|
docker manifest push unsend/$APP_NAME:$APP_VERSION
|
||||||
|
done
|
||||||
|
|
||||||
- name: Create and push Github Container Registry manifest
|
- name: Create and push Github Container Registry manifest
|
||||||
run: |
|
run: |
|
||||||
APP_VERSION="$(git name-rev --tags --name-only $(git rev-parse HEAD) | head -n 1 | sed 's/\^0//')"
|
APP_VERSION="$(git name-rev --tags --name-only $(git rev-parse HEAD) | head -n 1 | sed 's/\^0//')"
|
||||||
GIT_SHA="$(git rev-parse HEAD)"
|
GIT_SHA="$(git rev-parse HEAD)"
|
||||||
|
|
||||||
|
for APP_NAME in unsend smtp-proxy; do
|
||||||
docker manifest create \
|
docker manifest create \
|
||||||
ghcr.io/unsend-dev/unsend:latest \
|
ghcr.io/unsend-dev/$APP_NAME:latest \
|
||||||
--amend ghcr.io/unsend-dev/unsend-amd64:latest \
|
--amend ghcr.io/unsend-dev/$APP_NAME-amd64:latest \
|
||||||
--amend ghcr.io/unsend-dev/unsend-arm64:latest \
|
--amend ghcr.io/unsend-dev/$APP_NAME-arm64:latest
|
||||||
|
|
||||||
docker manifest create \
|
docker manifest create \
|
||||||
ghcr.io/unsend-dev/unsend:$GIT_SHA \
|
ghcr.io/unsend-dev/$APP_NAME:$GIT_SHA \
|
||||||
--amend ghcr.io/unsend-dev/unsend-amd64:$GIT_SHA \
|
--amend ghcr.io/unsend-dev/$APP_NAME-amd64:$GIT_SHA \
|
||||||
--amend ghcr.io/unsend-dev/unsend-arm64:$GIT_SHA \
|
--amend ghcr.io/unsend-dev/$APP_NAME-arm64:$GIT_SHA
|
||||||
|
|
||||||
docker manifest create \
|
docker manifest create \
|
||||||
ghcr.io/unsend-dev/unsend:$APP_VERSION \
|
ghcr.io/unsend-dev/$APP_NAME:$APP_VERSION \
|
||||||
--amend ghcr.io/unsend-dev/unsend-amd64:$APP_VERSION \
|
--amend ghcr.io/unsend-dev/$APP_NAME-amd64:$APP_VERSION \
|
||||||
--amend ghcr.io/unsend-dev/unsend-arm64:$APP_VERSION \
|
--amend ghcr.io/unsend-dev/$APP_NAME-arm64:$APP_VERSION
|
||||||
|
|
||||||
docker manifest push ghcr.io/unsend-dev/unsend:latest
|
docker manifest push ghcr.io/unsend-dev/$APP_NAME:latest
|
||||||
docker manifest push ghcr.io/unsend-dev/unsend:$GIT_SHA
|
docker manifest push ghcr.io/unsend-dev/$APP_NAME:$GIT_SHA
|
||||||
docker manifest push ghcr.io/unsend-dev/unsend:$APP_VERSION
|
docker manifest push ghcr.io/unsend-dev/$APP_NAME:$APP_VERSION
|
||||||
|
done
|
||||||
|
45
apps/smtp-server/Dockerfile
Normal file
45
apps/smtp-server/Dockerfile
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# Stage 1: Build stage
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
|
# Install pnpm (package manager) globally
|
||||||
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
|
# Set working directory for the application
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy configuration files first
|
||||||
|
COPY package.json tsconfig.json tsup.config.ts ./
|
||||||
|
|
||||||
|
# Install dependencies (including devDependencies)
|
||||||
|
RUN pnpm install
|
||||||
|
|
||||||
|
# Copy the source code
|
||||||
|
COPY src/ ./src/
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
RUN pnpm run build
|
||||||
|
|
||||||
|
|
||||||
|
# Remove development dependencies to reduce size
|
||||||
|
RUN pnpm prune --prod
|
||||||
|
|
||||||
|
# Stage 2: Production stage
|
||||||
|
FROM node:20-alpine AS production
|
||||||
|
|
||||||
|
# Set working directory in the final image
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy necessary files from the builder stage: production node_modules, build output, and package definition
|
||||||
|
COPY --from=builder /app/node_modules ./node_modules
|
||||||
|
|
||||||
|
# Copy only the necessary files from builder
|
||||||
|
COPY --from=builder /app/dist ./dist
|
||||||
|
COPY --from=builder /app/package.json ./package.json
|
||||||
|
|
||||||
|
|
||||||
|
# Expose SMTP ports (standard SMTP, SMTPS, and alternative ports)
|
||||||
|
EXPOSE 25 465 587 2465 2587
|
||||||
|
|
||||||
|
|
||||||
|
# Run the SMTP server
|
||||||
|
CMD ["node", "dist/server.js"]
|
29
apps/smtp-server/docker-compose.yml
Normal file
29
apps/smtp-server/docker-compose.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
name: unsend-smtp-server
|
||||||
|
|
||||||
|
services:
|
||||||
|
smtp-server:
|
||||||
|
container_name: unsend-smtp-server
|
||||||
|
image: unsend/smtp-proxy:latest
|
||||||
|
# Pass necessary environment variables
|
||||||
|
environment:
|
||||||
|
SMTP_AUTH_USERNAME: "unsend" # can be anything, just use the same while sending emails
|
||||||
|
UNSEND_BASE_URL: "https://app.unsend.dev" # your self hosted unsend instance url
|
||||||
|
|
||||||
|
# Uncomment this if you have SSL certificates. port 465 and 2465 will be using SSL
|
||||||
|
# UNSEND_API_KEY_PATH: "/certs/server.key"
|
||||||
|
# UNSEND_API_CERT_PATH: "/certs/server.crt"
|
||||||
|
# If you have SSL certificates, mount them here (read-only recommended)
|
||||||
|
|
||||||
|
# volumes:
|
||||||
|
# - ./certs/server.key:/certs/server.key:ro
|
||||||
|
# - ./certs/server.crt:/certs/server.crt:ro
|
||||||
|
|
||||||
|
# Expose the SMTP ports
|
||||||
|
ports:
|
||||||
|
- "25:25"
|
||||||
|
- "587:587"
|
||||||
|
- "2587:2587"
|
||||||
|
- "465:465"
|
||||||
|
- "2465:2465"
|
||||||
|
# Restart always or on-failure, depending on preference
|
||||||
|
restart: unless-stopped
|
@@ -81,10 +81,9 @@ const serverOptions: SMTPServerOptions = {
|
|||||||
replyTo: parsed.replyTo?.text,
|
replyTo: parsed.replyTo?.text,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("Parsed email data:", emailObject); // Debug statement
|
|
||||||
|
|
||||||
sendEmailToUnsend(emailObject, session.user)
|
sendEmailToUnsend(emailObject, session.user)
|
||||||
.then(() => callback())
|
.then(() => callback())
|
||||||
|
.then(() => console.log("Email sent successfully to: ", emailObject.to))
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("Failed to send email:", error.message);
|
console.error("Failed to send email:", error.message);
|
||||||
callback(error);
|
callback(error);
|
||||||
@@ -104,18 +103,22 @@ const serverOptions: SMTPServerOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function startServers() {
|
function startServers() {
|
||||||
|
if (SSL_KEY_PATH && SSL_CERT_PATH) {
|
||||||
// Implicit SSL/TLS for ports 465 and 2465
|
// Implicit SSL/TLS for ports 465 and 2465
|
||||||
[465, 2465].forEach((port) => {
|
[465, 2465].forEach((port) => {
|
||||||
const server = new SMTPServer({ ...serverOptions, secure: true });
|
const server = new SMTPServer({ ...serverOptions, secure: true });
|
||||||
|
|
||||||
server.listen(port, () => {
|
server.listen(port, () => {
|
||||||
console.log(`Implicit SSL/TLS SMTP server is listening on port ${port}`);
|
console.log(
|
||||||
|
`Implicit SSL/TLS SMTP server is listening on port ${port}`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("error", (err) => {
|
server.on("error", (err) => {
|
||||||
console.error(`Error occurred on port ${port}:`, err);
|
console.error(`Error occurred on port ${port}:`, err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// STARTTLS for ports 25, 587, and 2587
|
// STARTTLS for ports 25, 587, and 2587
|
||||||
[25, 587, 2587].forEach((port) => {
|
[25, 587, 2587].forEach((port) => {
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
const nodemailer = require("nodemailer");
|
const nodemailer = require("nodemailer");
|
||||||
|
|
||||||
const transporter = nodemailer.createTransport({
|
const transporter = nodemailer.createTransport({
|
||||||
host: "smtp.unsend.dev",
|
host: "localhost",
|
||||||
port: 2587,
|
port: 25,
|
||||||
secure: false,
|
secure: false,
|
||||||
auth: {
|
auth: {
|
||||||
user: "unsend",
|
user: "unsend",
|
||||||
|
Reference in New Issue
Block a user