{"id":29540742,"url":"https://github.com/ivpn/mailx","last_synced_at":"2025-07-17T08:39:46.601Z","repository":{"id":303958035,"uuid":"1015214251","full_name":"ivpn/mailx","owner":"ivpn","description":"Audited, Open-Source Email Aliasing Service","archived":false,"fork":false,"pushed_at":"2025-07-10T11:45:00.000Z","size":953,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-10T17:59:38.878Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://mailx.net","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ivpn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-07T07:10:07.000Z","updated_at":"2025-07-10T11:44:52.000Z","dependencies_parsed_at":"2025-07-10T18:25:20.267Z","dependency_job_id":null,"html_url":"https://github.com/ivpn/mailx","commit_stats":null,"previous_names":["ivpn/mailx"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/ivpn/mailx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivpn%2Fmailx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivpn%2Fmailx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivpn%2Fmailx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivpn%2Fmailx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivpn","download_url":"https://codeload.github.com/ivpn/mailx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivpn%2Fmailx/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265586192,"owners_count":23792864,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-17T08:39:41.514Z","updated_at":"2025-07-17T08:39:46.595Z","avatar_url":"https://github.com/ivpn.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Email Service\n\n## API\n\n- Go\n- Fiber (API, middleware)\n- Gorm (ORM)\n- MariaDB (Database)\n- Redis (Cache)\n- Docker (Containerization)\n- Swagger (API Documentation)\n\n## App\n\n- TypeScript\n- Vue.js\n- Vite (Bundler)\n- Tailwind (Styling)\n- Docker (Containerization)\n\n## Mailserver\n\n- [Docker Mailserver](https://github.com/docker-mailserver/docker-mailserver)  \n\n## Installation\n\n### Prerequisites\n\n- Docker: [Install Docker](https://docs.docker.com/get-docker/)\n- Docker Compose: [Install Docker Compose](https://docs.docker.com/compose/install/)\n\n\u003e [!IMPORTANT]\n\u003e Docker Mailserver officially supports Linux. If you want to run it on macOS, please read [this](https://github.com/docker-mailserver/docker-mailserver/issues/3648).\n\n### Config\n```bash\ncp api/.env.sample api/.env\ncp app/.env.sample app/.env\ncp mailserver/.env.sample mailserver/.env\nmkdir -p mailserver/docker-data/dms/config/rspamd/override.d\ncp mailserver/config/postfix-main.cf.sample mailserver/docker-data/dms/config/postfix-main.cf\ncp mailserver/config/postfix-virtual.cf.sample mailserver/docker-data/dms/config/postfix-virtual.cf\ncp mailserver/config/postfix-aliases.cf.sample mailserver/docker-data/dms/config/postfix-aliases.cf\ncp mailserver/config/user-patches.sh.sample mailserver/docker-data/dms/config/user-patches.sh\ncp mailserver/config/rspamd/override.d/milter_headers.conf.sample mailserver/docker-data/dms/config/rspamd/override.d/milter_headers.conf\n```\n\n\u003e [!IMPORTANT]\n\u003e Make sure to set up the required config:\n\u003e - api/.env: `DOMAINS`, `SMTP_CLIENT_*`\n\u003e - app/src/env.json: `DOMAINS`\n\u003e - mailserver/.env: `HOSTNAME`\n\u003e - mailserver/docker-data/dms/config/postfix-virtual.cf: `@your-domain.net curl_email`\n\n\u003e [!TIP]\n\u003e For local testing, you can use [MailHog](https://github.com/mailhog/MailHog) or [MailTrap](https://mailtrap.io/email-sandbox/) as outbound SMTP client (`SMTP_CLIENT_*`).\n\n### API + App\n\n#### Move to api directory\n```bash\ncd api\n```\n\n#### Run\n```bash\ndocker compose up -d\n```\n\nApp:  \nhttp://localhost:3001  \n\nAPI:  \nhttp://localhost:3000  \n\n### Mailserver\n\n#### Move to mailserver directory\n```bash\ncd mailserver\n```\n\n#### Run\n```bash\n# localhost\ndocker compose up -d\n\n# Staging|Production\ndocker compose -f compose.deploy.yml up -d\n```\n\n#### Setup Postfix\n```bash\ndocker exec -it mailserver sh\n\n# Build the db file\npostmap /etc/postfix/virtual\n\n# Update the alias table\nnewaliases\n\n# Enable DKIM signing, this will output the contents of DKIM TXT DNS record (mail._domainkey.domain.com)\nsetup config dkim selector mail\n\n# Restart Postfix\nsupervisorctl restart postfix\n\n# Show logs\nsetup debug show-mail-logs\n```\n\n#### Setup DKIM Signing\n\nUpdate dkim_signing.conf:\n```bash\nnano docker-data/dms/config/rspamd/override.d/dkim_signing.conf\n```\n\ndkim_signing.conf:\n```conf\n# documentation: https://rspamd.com/doc/modules/dkim_signing.html\n\nenabled = true;\n\nsign_authenticated = true;\nsign_local = true;\ntry_fallback = false;\n\nuse_domain = \"header\";\nuse_domain_sign_local = \"header\";\nuse_redis = false; # don't change unless Redis also provides the DKIM keys\nuse_esld = true;\nallow_username_mismatch = true;\n\ncheck_pubkey = false; # you want to use this in the beginning\n\ndomain {\n    domain.com {\n        path = \"/tmp/docker-mailserver/rspamd/dkim/rsa-2048-mail-domain.com.private.txt\";\n        selector = \"mail\";\n    }\n}\n```\n\nRestart Mailserver:\n```bash\ndocker compose down\ndocker compose up -d\n```\n\nTest DKIM signing with https://dkimvalidator.com:\n```bash\necho \"Test email\" | mail -s \"Test email\" wyygMXeSfnzl5l@dkimvalidator.com\n```\n\n#### Update Mailserver\n```bash\ndocker compose pull\ndocker compose down\ndocker compose up -d\n```\n\n\n## Add New Domain\n\n### Mailserver\n\n#### Update postfix-virtual.cf:\n```bash\nnano docker-data/dms/config/postfix-virtual.cf\n@domain.com curl_email\n```\n\n#### Setup Postfix:\n```bash\ndocker exec -it mailserver sh\npostmap /etc/postfix/virtual\nnewaliases\nsetup config dkim selector mail domain domain.com\nsupervisorctl restart postfix\n```\n\n#### Update dkim_signing.conf:\n```bash\nnano docker-data/dms/config/rspamd/override.d/dkim_signing.conf\ndomain.com {\n    path = \"/tmp/docker-mailserver/rspamd/dkim/rsa-2048-mail-domain.com.private.txt\";\n    selector = \"mail\";\n}\n```\n\n#### Restart mailserver:\n```bash\ndocker compose down\ndocker compose -f compose.deploy.yml up -d\n```\n\n### DNS Records\n\n#### MX Records:\n```\ndomain.com. . 14400 IN MX 10 mail.domain.com.\nmail.domain.com. . 14400 IN MX 10 MAIL_SERVER_IPV4\n```\n\n#### SPF Records:\n```\ndomain.com. 3600 IN TXT \"v=spf1 ip4:MAIL_SERVER_IPV4 -all\"\nmail.domain.com. 3600 IN TXT \"v=spf1 ip4:MAIL_SERVER_IPV4 -all\"\n```\n\n#### DMARC (TXT record):\n```\n_dmarc.mail.domain.com. 3600 IN TXT v=DMARC1; p=quarantine\n````\n\nDKIM (TXT record):\n```\nmail._domainkey.domain.com. 3600 IN TXT v=DKIM1;k=rsa;p=DKIM_PUBLIC_KEY\n```\n\n### API\n\n#### Update .env:\n```bash\nnano .env\nDOMAINS=domain1.com,domain2.com\n```\n\n#### Restart api:\n```bash\ndocker compose down\ndocker compose up -d\n```\n\n### App\n\n#### Update GitHub Actions env variables:\n```bash\nSTAGING_VITE_DOMAINS=domain1.com,domain2.com\nPROD_VITE_DOMAINS=domain1.com,domain2.com\n```\n\n\n## Restore DB from backup\n\nDB backup is stored locally on the host machine in the `${HOME}/backups` directory.\n\n### Unpack backup\n```bash\ncd ${HOME}/backups\ngpg -o backup.tar.gz -d backup-latest.tar.gz.gpg\ntar -xvf backup.tar.gz\n```\n\n### Restore DB\n\n```bash\n# Stop the containers\ndocker compose down\n\n# Clone the volume\ndocker volume create email_db_clone\ndocker run --rm -v email_db:/from -v email_db_clone:/to alpine sh -c \"cp -a /from/. /to/\"\n\n# Remove the original volume\ndocker volume rm email_db\n\n# Recreate the original volume from backup\ndocker run -d --name restore -v email_db:/email_db alpine\ndocker cp /unpacked_volume_dir/. restore:/email_db\ndocker stop restore \u0026\u0026 docker rm restore\n\n# Start the containers\ndocker compose up -d\n```\n\n## Test\nRun API tests:  \n```bash\ngo test ./... -v\ngo vet ./...\ngosec ./...\n```\n\nSend test email:  \n```bash\ndocker exec -it mailserver sh\necho \"Test email body\" | mail -s \"Test subject\" example.alias@example.net\n```\n\n## API Documentation\nAPI docs:  \nhttp://localhost:3000/docs  \n\nGenerate API docs:  \n```bash\ncd api\nswag init -g cmd/main.go\n```\n\n\u003e [!TIP]\n\u003e With [Task](https://github.com/go-task/task), run `task docs` to generate API documentation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivpn%2Fmailx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivpn%2Fmailx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivpn%2Fmailx/lists"}