diff options
| -rw-r--r-- | Makefile | 43 | ||||
| -rw-r--r-- | config.go | 6 | ||||
| -rw-r--r-- | db.go | 2 | ||||
| -rw-r--r-- | domain.go | 17 | ||||
| -rw-r--r-- | domain_test.go | 18 | ||||
| -rwxr-xr-x | env.sh | 1 | ||||
| -rw-r--r-- | schema.txt | 30 | ||||
| -rw-r--r-- | server.go | 5 |
8 files changed, 97 insertions, 25 deletions
@@ -15,6 +15,14 @@ else VERBOSE:= endif +# Allow use of external networks. EXTERNAL=1 +ifdef EXTERNAL + EXTERNAL:=-external +else + EXTERNAL:= +endif + + IMPORT_FILE:=./import.go APP:=mailer @@ -31,10 +39,10 @@ all: kill build run clean: kill @(rm $(IMPORT_FILE) 2>/dev/null && echo "Removing import file..." ) || true @(rm $(FREEMAIL_DB_CREDENTIALS) 2>/dev/null echo && "Removing sqlite3 database..." ) || true -# @(rm ../$(APP).tar.gz 1>&2 2>/dev/null && echo "Removing tar archiv...") || true + @(rm $(APP).tar.gz 1>&2 2>/dev/null && echo "Removing tar archiv...") || true @(rm _env.sh 1>&2 2>/dev/null && echo "Removing _env.sh...") || true @(rm $(APP) 2>/dev/null && echo "Removing binary ($(APP))...") || true -# @(rm ../start.sh 1>&2 2>/dev/null && echo "Removing startup script...") || true + @(rm start.sh 1>&2 2>/dev/null && echo "Removing startup script...") || true @echo "Done." build: import @@ -44,8 +52,9 @@ run: _test_build ./$(APP) & kill: - @echo "Killing running instances..." - @pkill $(APP) || true + @(pgrep $(APP) && \ + echo "Killing running instances..." && \ + pkill $(APP) ) || true create_import: @if [ ! -f $(IMPORT_FILE) ] ; \ @@ -73,31 +82,21 @@ database_all: sqlite3 mysql postgresql @echo "Created import file for all databases." pack: gen_config - @cd .. && \ echo "#!/bin/sh" > start.sh && \ - echo "cd app && . ./_env.sh && ./$(APP)" >> start.sh && \ + echo ". ./_env.sh && ./$(APP)" >> start.sh && \ chmod +x start.sh && \ - tar czf $(APP).tar.gz start.sh app/$(APP) app/_env.sh views static $(FREEMAIL_DB_DIR) 2>/dev/null && \ + tar czf $(APP).tar.gz start.sh $(APP) _env.sh views static $(FREEMAIL_DB_DIR) 2>/dev/null && \ rm start.sh 2>/dev/null && \ - echo "\n../$(APP).tar.gz is ready." || \ + echo "\n/$(APP).tar.gz is ready." || \ (echo "Run \"make build\" first." && exit 1) test: import - FREEMAIL_DB_CREDENTIALS=":memory:" go test $(RACE) $(VERBOSE) + FREEMAIL_DB_CREDENTIALS=":memory:" go test $(RACE) $(VERBOSE) $(EXTERNAL) @(rm $(IMPORT_FILE) 2>/dev/null && echo "Removing import file..." ) || true -test_all: import - FREEMAIL_DB_CREDENTIALS=":memory:" go test $(RACE) $(VERBOSE) -v -tags all - -test_dependencies: import - FREEMAIL_DB_CREDENTIALS=":memory:" go test $(RACE) $(VERBOSE) -tags dep - -benchmark: - FREEMAIL_DB_CREDENTIALS=":memory:" go test $(VERBOSE) -bench=".*" -tags general - -benchmark_dependencies: import - export DB_FREEMAIL_LOG=false - FREEMAIL_DB_CREDENTIALS=":memory:" go test $(VERBOSE) -bench=".*" -tags dep +benchmark: import + DB_FREEMAIL_LOG=false FREEMAIL_DB_CREDENTIALS=":memory:" go test $(VERBOSE) -bench=".*" + @(rm $(IMPORT_FILE) 2>/dev/null && echo "Removing import file..." ) || true _test_build: @if [ ! -f ./$(APP) ] || [ ! -x ./$(APP) ]; then \ @@ -127,7 +126,7 @@ gen_config: _test_build echo "export FREEMAIL_SECRET=$(FREEMAIL_SECRET)" >> _env.sh @echo "" @echo "# Smtp" >> _env.sh - echo "export FREEMAIL_SMTP_MAILER=$(FREEMAIL_SMTP_MAILER)" >> _env.sh + echo "export FREEMAIL_SMTP_MAILER_MX=$(FREEMAIL_SMTP_MAILER_MX)" >> _env.sh echo "export FREEMAIL_SMTP_PASSWORD=$(FREEMAIL_SMTP_PASSWORD)" >> _env.sh echo "export FREEMAIL_SMTP_ADRESS=$(FREEMAIL_SMTP_ADRESS)" >> _env.sh @chmod +x _env.sh @@ -32,10 +32,14 @@ func checkConfig() { if check == "" { log.Fatal("Env FREEMAIL_HTTP_PORT not found.") } + check = os.Getenv("FREEMAIL_SMTP_MAILER_MX") + if check == "" { + log.Fatal("Env FREEMAIL_MAILER_MX not found.") + } /* check = os.Getenv("FREEMAIL_SMTP_MAILER") if check == "" { - log.Fatal("Env FREEMAIL_MAILTER not found.") + log.Fatal("Env FREEMAIL_MAILER not found.") } check = os.Getenv("FREEMAIL_SMTP_PASSWORD") if check == "" { @@ -30,7 +30,7 @@ func InitDB() { Db.Debug().AutoMigrate(&vA) Db.Model(&vU).AddUniqueIndex("idx_virtuser_email", "email") - Db.Model(&vU).AddForeignKey("domain_id", "virtual_domains(id)", "CASCADE", "RESTRICT") + //Db.Model(&vU).AddForeignKey("domain_id", "virtual_domains(id)", "CASCADE", "RESTRICT") /* Db.Model(&u).AddUniqueIndex("idx_user_name", "name") Db.Model(&u).AddUniqueIndex("idx_user_email", "email") @@ -45,6 +45,23 @@ func (vD VirtualDomain) ValidateDomain() bool { } return true } +func (vD VirtualDomain) ValidateDomainMX(ref string) bool { + if vD.Name == "" { + return false + } + mx, err := net.LookupMX(vD.Name) + if err != nil { + log.Println(err) + return false + } + match := false + for _, v := range mx { + if v.Host == ref { + match = true + } + } + return match +} func GetDomain(email string) string { fragments := strings.Split(email, "@") diff --git a/domain_test.go b/domain_test.go index 6f90ede..456d301 100644 --- a/domain_test.go +++ b/domain_test.go @@ -1,9 +1,13 @@ package main import ( + "flag" + "os" "testing" ) +var testExternal = flag.Bool("external", false, "allow use of external networks during long test") + func TestCreateDomain(t *testing.T) { d := VirtualDomain{Name: "example.org"} if !d.CreateDomain() { @@ -41,6 +45,20 @@ func TestValidateDomain(t *testing.T) { } } +func TestValidateDomainMX(t *testing.T) { + if testing.Short() || !*testExternal { + t.Skip("Skipping test to avoid external network.") + } + d := VirtualDomain{Name: "heise.de"} + if d.ValidateDomainMX(os.Getenv("FREEMAIL_SMTP_MAILER_MX")) { + t.Fatal("heise.de MX record doesn't point to this server.") + } + d.Name = "iamfabulous.de" + if !d.ValidateDomainMX(os.Getenv("FREEMAIL_SMTP_MAILER_MX")) { + t.Fatal(os.Getenv("FREEMAIL_SMTP_MAILER_MX") + " MX should point to this server.") + } +} + func TestGetDomain(t *testing.T) { domain := GetDomain("foo@example.org") if domain != "example.org" { @@ -17,6 +17,7 @@ export FREEMAIL_HTTP_IP=127.0.0.1 export FREEMAIL_HTTP_PORT=8080 # SMTP +export FREEMAIL_SMTP_MAILER_MX="mx.example.org" #export FREEMAIL_SMTP_MAILER="smtp.example.org:25" #export FREEMAIL_SMTP_PASSWORD="password" #export FREEMAIL_SMTP_ADRESS="foo@example.org" diff --git a/schema.txt b/schema.txt new file mode 100644 index 0000000..864bda3 --- /dev/null +++ b/schema.txt @@ -0,0 +1,30 @@ +MariaDB [mailserver]> explain virtual_users; ++-----------+--------------+------+-----+---------+----------------+ +| Field | Type | Null | Key | Default | Extra | ++-----------+--------------+------+-----+---------+----------------+ +| id | int(11) | NO | PRI | NULL | auto_increment | +| domain_id | int(11) | NO | MUL | NULL | | +| password | varchar(32) | NO | | NULL | | +| email | varchar(100) | NO | UNI | NULL | | ++-----------+--------------+------+-----+---------+----------------+ +4 rows in set (0.00 sec) + +MariaDB [mailserver]> explain virtual_domains; ++-------+-------------+------+-----+---------+----------------+ +| Field | Type | Null | Key | Default | Extra | ++-------+-------------+------+-----+---------+----------------+ +| id | int(11) | NO | PRI | NULL | auto_increment | +| name | varchar(50) | NO | | NULL | | ++-------+-------------+------+-----+---------+----------------+ +2 rows in set (0.00 sec) + +MariaDB [mailserver]> explain virtual_aliases; ++-------------+--------------+------+-----+---------+----------------+ +| Field | Type | Null | Key | Default | Extra | ++-------------+--------------+------+-----+---------+----------------+ +| id | int(11) | NO | PRI | NULL | auto_increment | +| domain_id | int(11) | NO | MUL | NULL | | +| source | varchar(100) | NO | | NULL | | +| destination | varchar(100) | NO | | NULL | | ++-------------+--------------+------+-----+---------+----------------+ +4 rows in set (0.00 sec) @@ -2,6 +2,7 @@ package main import ( "errors" + "os" ) func CreateNewEntry(email, password string) error { @@ -19,7 +20,9 @@ func CreateNewEntry(email, password string) error { vD.Name = GetDomain(vU.Email) if !vD.ValidateDomain() { - return errors.New("This doesn't look like a good domain. Host not found.") + if !vD.ValidateDomainMX(os.Getenv("FREEMAIL_SMTP_MAILER_MX")) { + return errors.New("This doesn't look like a good domain. Host not found.") + } } if !vD.DomainExists() { |
