1
0
mirror of https://github.com/directorz/mailfull-go.git synced 2025-12-20 19:17:02 +00:00

16 Commits

Author SHA1 Message Date
teru
46cf349015 Merge pull request #19 from directorz/feature/vendoring_glide
Feature/vendoring glide
2016-09-29 12:12:28 +09:00
teru
9be507565d Bump version to v0.0.6 2016-09-29 12:12:03 +09:00
teru
58b4e49fe8 Use golang:1.7.1 2016-09-29 12:10:15 +09:00
teru
cb6e9ce2c5 Use Glide instead of gom 2016-09-29 12:08:07 +09:00
teru
db554a1da1 Merge pull request #18 from directorz/feature/no_commit_flag
Feature/no commit flag
2016-08-28 17:12:46 +09:00
teru
708e132ccc Bump version to v0.0.5 2016-08-28 17:10:32 +09:00
teru
3a1d4a588c Add a option to subcommands #7 2016-08-28 17:09:09 +09:00
teru
50d429ad78 Implement to parse -n flag #7 2016-08-28 17:06:52 +09:00
teru
0118652074 Merge pull request #17 from directorz/feature/implements
Feature/implements
2016-08-23 18:08:22 +09:00
teru
bf4b63556a Bump version to v0.0.4 2016-08-23 18:05:52 +09:00
teru
24ee3c26b0 Rename a file 2016-08-23 18:04:55 +09:00
teru
49dd05f3bf Change output format of domains subcommands #8 2016-08-23 18:04:30 +09:00
teru
009ee84e63 Implement subcommands: domaindisable, domainenable #8 2016-08-23 18:04:08 +09:00
teru
281d5a4a9d Implement disable/enable a Domain #8 2016-08-23 18:03:45 +09:00
teru
c2dca41057 Add a field to Domain struct 2016-08-23 13:40:20 +09:00
teru
4f99f11732 Update installation guide 2016-08-23 13:39:35 +09:00
28 changed files with 592 additions and 36 deletions

View File

@@ -1,6 +0,0 @@
gom 'github.com/BurntSushi/toml'
gom 'github.com/armon/go-radix'
gom 'github.com/bgentry/speakeasy'
gom 'github.com/jsimonetti/pwscheme'
gom 'github.com/mattn/go-isatty'
gom 'github.com/mitchellh/cli'

View File

@@ -10,20 +10,20 @@ VERSION=$(patsubst "%",%,$(lastword $(shell grep 'const Version' version.go)))
default: build default: build
installdeps: installdeps:
gom install glide install -v
build: build:
go build -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -v -o build/mailfull_$(GOOS)_$(GOARCH)/mailfull cmd/mailfull/main.go go build -v -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -o build/mailfull_$(GOOS)_$(GOARCH)/mailfull cmd/mailfull/mailfull.go
build-linux-amd64: build-linux-amd64:
docker run --rm -v $(PWD):/go/src/github.com/directorz/mailfull-go -w /go/src/github.com/directorz/mailfull-go \ docker run --rm -v $(PWD):/go/src/github.com/directorz/mailfull-go -w /go/src/github.com/directorz/mailfull-go \
-e GOOS=linux -e GOARCH=amd64 golang:1.7 \ -e GOOS=linux -e GOARCH=amd64 golang:1.7.1 \
go build -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -v -o "build/mailfull_linux_amd64/mailfull" cmd/mailfull/main.go go build -v -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -o "build/mailfull_linux_amd64/mailfull" cmd/mailfull/mailfull.go
build-linux-386: build-linux-386:
docker run --rm -v $(PWD):/go/src/github.com/directorz/mailfull-go -w /go/src/github.com/directorz/mailfull-go \ docker run --rm -v $(PWD):/go/src/github.com/directorz/mailfull-go -w /go/src/github.com/directorz/mailfull-go \
-e GOOS=linux -e GOARCH=386 golang:1.7 \ -e GOOS=linux -e GOARCH=386 golang:1.7.1 \
go build -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -v -o "build/mailfull_linux_386/mailfull" cmd/mailfull/main.go go build -v -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -o "build/mailfull_linux_386/mailfull" cmd/mailfull/mailfull.go
release: release-linux-amd64 release-linux-386 release: release-linux-amd64 release-linux-386

View File

@@ -16,6 +16,11 @@ Features
Installation Installation
------------ ------------
### Binary
You can download archive file from [releases page](https://github.com/directorz/mailfull-go/releases) .
Download and unpack the archive file, and put the binary file to somewhere you want.
### go get ### go get
Installed in `$GOPATH/bin` Installed in `$GOPATH/bin`

View File

@@ -20,7 +20,7 @@ func (c *AliasDomainAddCommand) Synopsis() string {
func (c *AliasDomainAddCommand) Help() string { func (c *AliasDomainAddCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s domain target %s %s [-n] domain target
Description: Description:
%s %s
@@ -30,6 +30,10 @@ Required Args:
The domain name that you want to create. The domain name that you want to create.
target target
The target domain name. The target domain name.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -39,6 +43,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *AliasDomainAddCommand) Run(args []string) int { func (c *AliasDomainAddCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 2 { if len(args) != 2 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -64,6 +74,10 @@ func (c *AliasDomainAddCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -20,7 +20,7 @@ func (c *AliasDomainDelCommand) Synopsis() string {
func (c *AliasDomainDelCommand) Help() string { func (c *AliasDomainDelCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s domain %s %s [-n] domain
Description: Description:
%s %s
@@ -28,6 +28,10 @@ Description:
Required Args: Required Args:
domain domain
The domain name that you want to delete. The domain name that you want to delete.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -37,6 +41,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *AliasDomainDelCommand) Run(args []string) int { func (c *AliasDomainDelCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 1 { if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -55,6 +65,10 @@ func (c *AliasDomainDelCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -21,7 +21,7 @@ func (c *AliasUserAddCommand) Synopsis() string {
func (c *AliasUserAddCommand) Help() string { func (c *AliasUserAddCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s address target [target...] %s %s [-n] address target [target...]
Description: Description:
%s %s
@@ -31,6 +31,10 @@ Required Args:
The email address that you want to create. The email address that you want to create.
target target
Target email addresses. Target email addresses.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -40,6 +44,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *AliasUserAddCommand) Run(args []string) int { func (c *AliasUserAddCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) < 2 { if len(args) < 2 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -73,6 +83,10 @@ func (c *AliasUserAddCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -21,7 +21,7 @@ func (c *AliasUserDelCommand) Synopsis() string {
func (c *AliasUserDelCommand) Help() string { func (c *AliasUserDelCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s address %s %s [-n] address
Description: Description:
%s %s
@@ -29,6 +29,10 @@ Description:
Required Args: Required Args:
address address
The email address that you want to delete. The email address that you want to delete.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -38,6 +42,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *AliasUserDelCommand) Run(args []string) int { func (c *AliasUserDelCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 1 { if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -63,6 +73,10 @@ func (c *AliasUserDelCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -21,7 +21,7 @@ func (c *AliasUserModCommand) Synopsis() string {
func (c *AliasUserModCommand) Help() string { func (c *AliasUserModCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s address target [target...] %s %s [-n] address target [target...]
Description: Description:
%s %s
@@ -31,6 +31,10 @@ Required Args:
The email address that you want to modify. The email address that you want to modify.
target target
Target email addresses. Target email addresses.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -40,6 +44,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *AliasUserModCommand) Run(args []string) int { func (c *AliasUserModCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) < 2 { if len(args) < 2 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -82,6 +92,10 @@ func (c *AliasUserModCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -20,7 +20,7 @@ func (c *CatchAllSetCommand) Synopsis() string {
func (c *CatchAllSetCommand) Help() string { func (c *CatchAllSetCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s domain user %s %s [-n] domain user
Description: Description:
%s %s
@@ -30,6 +30,10 @@ Required Args:
The domain name. The domain name.
user user
The user name that you want to set as catchall user. The user name that you want to set as catchall user.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -39,6 +43,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *CatchAllSetCommand) Run(args []string) int { func (c *CatchAllSetCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 2 { if len(args) != 2 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -64,6 +74,10 @@ func (c *CatchAllSetCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -20,7 +20,7 @@ func (c *CatchAllUnsetCommand) Synopsis() string {
func (c *CatchAllUnsetCommand) Help() string { func (c *CatchAllUnsetCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s domain %s %s [-n] domain
Description: Description:
%s %s
@@ -28,6 +28,10 @@ Description:
Required Args: Required Args:
domain domain
The domain name. The domain name.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -37,6 +41,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *CatchAllUnsetCommand) Run(args []string) int { func (c *CatchAllUnsetCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 1 { if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -55,6 +65,10 @@ func (c *CatchAllUnsetCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -20,7 +20,7 @@ func (c *DomainAddCommand) Synopsis() string {
func (c *DomainAddCommand) Help() string { func (c *DomainAddCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s domain %s %s [-n] domain
Description: Description:
%s %s
@@ -28,6 +28,10 @@ Description:
Required Args: Required Args:
domain domain
The domain name that you want to create. The domain name that you want to create.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -37,6 +41,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *DomainAddCommand) Run(args []string) int { func (c *DomainAddCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 1 { if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -72,6 +82,10 @@ func (c *DomainAddCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -20,7 +20,7 @@ func (c *DomainDelCommand) Synopsis() string {
func (c *DomainDelCommand) Help() string { func (c *DomainDelCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s domain %s %s [-n] domain
Description: Description:
%s %s
@@ -28,6 +28,10 @@ Description:
Required Args: Required Args:
domain domain
The domain name that you want to delete. The domain name that you want to delete.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -37,6 +41,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *DomainDelCommand) Run(args []string) int { func (c *DomainDelCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 1 { if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -55,6 +65,10 @@ func (c *DomainDelCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -0,0 +1,97 @@
package command
import (
"fmt"
"github.com/directorz/mailfull-go"
)
// DomainDisableCommand represents a DomainDisableCommand.
type DomainDisableCommand struct {
Meta
}
// Synopsis returns a one-line synopsis.
func (c *DomainDisableCommand) Synopsis() string {
return "Disable a domain temporarily."
}
// Help returns long-form help text.
func (c *DomainDisableCommand) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s [-n] domain
Description:
%s
Required Args:
domain
The domain name that you want to disable.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
return txt[1:]
}
// Run runs the command and returns the exit status.
func (c *DomainDisableCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
domainName := args[0]
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
domain, err := repo.Domain(domainName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
if domain == nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", mailfull.ErrDomainNotExist)
return 1
}
domain.SetDisabled(true)
if err := repo.DomainUpdate(domain); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
return 0
}

View File

@@ -0,0 +1,97 @@
package command
import (
"fmt"
"github.com/directorz/mailfull-go"
)
// DomainEnableCommand represents a DomainEnableCommand.
type DomainEnableCommand struct {
Meta
}
// Synopsis returns a one-line synopsis.
func (c *DomainEnableCommand) Synopsis() string {
return "Enable a domain."
}
// Help returns long-form help text.
func (c *DomainEnableCommand) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s [-n] domain
Description:
%s
Required Args:
domain
The domain name that you want to enable.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
return txt[1:]
}
// Run runs the command and returns the exit status.
func (c *DomainEnableCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
domainName := args[0]
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
domain, err := repo.Domain(domainName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
if domain == nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", mailfull.ErrDomainNotExist)
return 1
}
domain.SetDisabled(false)
if err := repo.DomainUpdate(domain); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
return 0
}

View File

@@ -25,6 +25,7 @@ Usage:
Description: Description:
%s %s
Disabled domains are marked "!" the beginning.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -48,7 +49,12 @@ func (c *DomainsCommand) Run(args []string) int {
sort.Sort(mailfull.DomainSlice(domains)) sort.Sort(mailfull.DomainSlice(domains))
for _, domain := range domains { for _, domain := range domains {
fmt.Fprintf(c.UI.Writer, "%s\n", domain.Name()) disableStr := ""
if domain.Disabled() {
disableStr = "!"
}
fmt.Fprintf(c.UI.Writer, "%s%s\n", disableStr, domain.Name())
} }
return 0 return 0

View File

@@ -1,6 +1,9 @@
package command package command
import ( import (
"bytes"
"flag"
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
@@ -11,3 +14,17 @@ type Meta struct {
SubCmdName string SubCmdName string
Version string Version string
} }
// noCommitFlag returns true if `pargs` has "-n" flag.
// `pargs` is overwrites with non-flag arguments.
func noCommitFlag(pargs *[]string) (bool, error) {
nFlag := false
flagSet := flag.NewFlagSet("", flag.ContinueOnError)
flagSet.SetOutput(&bytes.Buffer{})
flagSet.BoolVar(&nFlag, "n", nFlag, "")
err := flagSet.Parse(*pargs)
*pargs = flagSet.Args()
return nFlag, err
}

View File

@@ -21,7 +21,7 @@ func (c *UserAddCommand) Synopsis() string {
func (c *UserAddCommand) Help() string { func (c *UserAddCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s address %s %s [-n] address
Description: Description:
%s %s
@@ -29,6 +29,10 @@ Description:
Required Args: Required Args:
address address
The email address that you want to create. The email address that you want to create.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -38,6 +42,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *UserAddCommand) Run(args []string) int { func (c *UserAddCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 1 { if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -70,6 +80,10 @@ func (c *UserAddCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -34,7 +34,7 @@ Required Args:
Optional Args: Optional Args:
password password
Specify the password instead of your typing. Specify the password instead of your typing.
This option is not recommended because the password will be visible in your shell history. This option is NOT recommended because the password will be visible in your shell history.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())

View File

@@ -21,7 +21,7 @@ func (c *UserDelCommand) Synopsis() string {
func (c *UserDelCommand) Help() string { func (c *UserDelCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s address %s %s [-n] address
Description: Description:
%s %s
@@ -29,6 +29,10 @@ Description:
Required Args: Required Args:
address address
The email address that you want to delete. The email address that you want to delete.
Optional Args:
-n
Don't update databases.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -38,6 +42,12 @@ Required Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *UserDelCommand) Run(args []string) int { func (c *UserDelCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 1 { if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -69,6 +79,10 @@ func (c *UserDelCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -22,7 +22,7 @@ func (c *UserPasswdCommand) Synopsis() string {
func (c *UserPasswdCommand) Help() string { func (c *UserPasswdCommand) Help() string {
txt := fmt.Sprintf(` txt := fmt.Sprintf(`
Usage: Usage:
%s %s address [password] %s %s [-n] address [password]
Description: Description:
%s %s
@@ -32,9 +32,11 @@ Required Args:
The email address that you want to update the password. The email address that you want to update the password.
Optional Args: Optional Args:
-n
Don't update databases.
password password
Specify the password instead of your typing. Specify the password instead of your typing.
This option is not recommended because the password will be visible in your shell history. This option is NOT recommended because the password will be visible in your shell history.
`, `,
c.CmdName, c.SubCmdName, c.CmdName, c.SubCmdName,
c.Synopsis()) c.Synopsis())
@@ -44,6 +46,12 @@ Optional Args:
// Run runs the command and returns the exit status. // Run runs the command and returns the exit status.
func (c *UserPasswdCommand) Run(args []string) int { func (c *UserPasswdCommand) Run(args []string) int {
noCommit, err := noCommitFlag(&args)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
}
if len(args) != 1 && len(args) != 2 { if len(args) != 1 && len(args) != 2 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help()) fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1 return 1
@@ -115,6 +123,10 @@ func (c *UserPasswdCommand) Run(args []string) int {
return 1 return 1
} }
if noCommit {
return 0
}
mailData, err := repo.MailData() mailData, err := repo.MailData()
if err != nil { if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err) fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -62,6 +62,14 @@ func main() {
meta.SubCmdName = c.Subcommand() meta.SubCmdName = c.Subcommand()
return &command.DomainDelCommand{Meta: meta}, nil return &command.DomainDelCommand{Meta: meta}, nil
}, },
"domaindisable": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.DomainDisableCommand{Meta: meta}, nil
},
"domainenable": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.DomainEnableCommand{Meta: meta}, nil
},
"aliasdomains": func() (cli.Command, error) { "aliasdomains": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand() meta.SubCmdName = c.Subcommand()
return &command.AliasDomainsCommand{Meta: meta}, nil return &command.AliasDomainsCommand{Meta: meta}, nil

View File

@@ -5,6 +5,7 @@ const (
DirNameConfig = ".mailfull" DirNameConfig = ".mailfull"
FileNameConfig = "config" FileNameConfig = "config"
FileNameDomainDisable = ".vdomaindisable"
FileNameAliasDomains = ".valiasdomains" FileNameAliasDomains = ".valiasdomains"
FileNameUsersPassword = ".vpasswd" FileNameUsersPassword = ".vpasswd"
FileNameUserForwards = ".forward" FileNameUserForwards = ".forward"

View File

@@ -70,6 +70,10 @@ func (r *Repository) generateDbDomains(md *MailData) error {
defer dbDomains.Close() defer dbDomains.Close()
for _, domain := range md.Domains { for _, domain := range md.Domains {
if domain.Disabled() {
continue
}
if _, err := fmt.Fprintf(dbDomains, "%s virtual\n", domain.Name()); err != nil { if _, err := fmt.Fprintf(dbDomains, "%s virtual\n", domain.Name()); err != nil {
return err return err
} }
@@ -95,6 +99,10 @@ func (r *Repository) generateDbDestinations(md *MailData) error {
defer dbDestinations.Close() defer dbDestinations.Close()
for _, domain := range md.Domains { for _, domain := range md.Domains {
if domain.Disabled() {
continue
}
// ho-ge.example.com -> ho_ge.example.com // ho-ge.example.com -> ho_ge.example.com
underscoredDomainName := domain.Name() underscoredDomainName := domain.Name()
underscoredDomainName = strings.Replace(underscoredDomainName, `-`, `_`, -1) underscoredDomainName = strings.Replace(underscoredDomainName, `-`, `_`, -1)
@@ -153,6 +161,10 @@ func (r *Repository) generateDbMaildirs(md *MailData) error {
defer dbMaildirs.Close() defer dbMaildirs.Close()
for _, domain := range md.Domains { for _, domain := range md.Domains {
if domain.Disabled() {
continue
}
for _, user := range domain.Users { for _, user := range domain.Users {
if _, err := fmt.Fprintf(dbMaildirs, "%s@%s %s/%s/Maildir/\n", user.Name(), domain.Name(), domain.Name(), user.Name()); err != nil { if _, err := fmt.Fprintf(dbMaildirs, "%s@%s %s/%s/Maildir/\n", user.Name(), domain.Name(), domain.Name(), user.Name()); err != nil {
return err return err
@@ -174,6 +186,10 @@ func (r *Repository) generateDbLocaltable(md *MailData) error {
defer dbLocaltable.Close() defer dbLocaltable.Close()
for _, domain := range md.Domains { for _, domain := range md.Domains {
if domain.Disabled() {
continue
}
// ho-ge.example.com -> ho_ge\.example\.com // ho-ge.example.com -> ho_ge\.example\.com
escapedDomainName := domain.Name() escapedDomainName := domain.Name()
escapedDomainName = strings.Replace(escapedDomainName, `-`, `_`, -1) escapedDomainName = strings.Replace(escapedDomainName, `-`, `_`, -1)
@@ -198,6 +214,10 @@ func (r *Repository) generateDbForwards(md *MailData) error {
defer dbForwards.Close() defer dbForwards.Close()
for _, domain := range md.Domains { for _, domain := range md.Domains {
if domain.Disabled() {
continue
}
// ho-ge.example.com -> ho_ge.example.com // ho-ge.example.com -> ho_ge.example.com
underscoredDomainName := domain.Name() underscoredDomainName := domain.Name()
underscoredDomainName = strings.Replace(underscoredDomainName, `-`, `_`, -1) underscoredDomainName = strings.Replace(underscoredDomainName, `-`, `_`, -1)
@@ -234,6 +254,10 @@ func (r *Repository) generateDbPasswords(md *MailData) error {
defer dbPasswords.Close() defer dbPasswords.Close()
for _, domain := range md.Domains { for _, domain := range md.Domains {
if domain.Disabled() {
continue
}
for _, user := range domain.Users { for _, user := range domain.Users {
if _, err := fmt.Fprintf(dbPasswords, "%s@%s:%s\n", user.Name(), domain.Name(), user.HashedPassword()); err != nil { if _, err := fmt.Fprintf(dbPasswords, "%s@%s:%s\n", user.Name(), domain.Name(), user.HashedPassword()); err != nil {
return err return err

121
domain.go
View File

@@ -11,6 +11,7 @@ import (
// Domain represents a Domain. // Domain represents a Domain.
type Domain struct { type Domain struct {
name string name string
disabled bool
Users []*User Users []*User
AliasUsers []*AliasUser AliasUsers []*AliasUser
CatchAllUser *CatchAllUser CatchAllUser *CatchAllUser
@@ -25,22 +26,41 @@ func (p DomainSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// NewDomain creates a new Domain instance. // NewDomain creates a new Domain instance.
func NewDomain(name string) (*Domain, error) { func NewDomain(name string) (*Domain, error) {
if !validDomainName(name) { d := &Domain{}
return nil, ErrInvalidDomainName
}
d := &Domain{ if err := d.setName(name); err != nil {
name: name, return nil, err
} }
return d, nil return d, nil
} }
// setName sets the name.
func (d *Domain) setName(name string) error {
if !validDomainName(name) {
return ErrInvalidDomainName
}
d.name = name
return nil
}
// Name returns name. // Name returns name.
func (d *Domain) Name() string { func (d *Domain) Name() string {
return d.name return d.name
} }
// SetDisabled disables the Domain if the input is true.
func (d *Domain) SetDisabled(disabled bool) {
d.disabled = disabled
}
// Disabled returns true if the Domain is disabled.
func (d *Domain) Disabled() bool {
return d.disabled
}
// Domains returns a Domain slice. // Domains returns a Domain slice.
func (r *Repository) Domains() ([]*Domain, error) { func (r *Repository) Domains() ([]*Domain, error) {
fileInfos, err := ioutil.ReadDir(r.DirMailDataPath) fileInfos, err := ioutil.ReadDir(r.DirMailDataPath)
@@ -62,6 +82,12 @@ func (r *Repository) Domains() ([]*Domain, error) {
continue continue
} }
disabled, err := r.domainDisabled(name)
if err != nil {
return nil, err
}
domain.SetDisabled(disabled)
domains = append(domains, domain) domains = append(domains, domain)
} }
@@ -94,9 +120,38 @@ func (r *Repository) Domain(domainName string) (*Domain, error) {
return nil, err return nil, err
} }
disabled, err := r.domainDisabled(name)
if err != nil {
return nil, err
}
domain.SetDisabled(disabled)
return domain, nil return domain, nil
} }
// domainDisabled returns true if the input Domain is disabled.
func (r *Repository) domainDisabled(domainName string) (bool, error) {
if !validDomainName(domainName) {
return false, ErrInvalidDomainName
}
fi, err := os.Stat(filepath.Join(r.DirMailDataPath, domainName, FileNameDomainDisable))
if err != nil {
if err.(*os.PathError).Err == syscall.ENOENT {
return false, nil
}
return false, err
}
if fi.IsDir() {
return false, ErrInvalidFormatDomainDisabled
}
return true, nil
}
// DomainCreate creates the input Domain. // DomainCreate creates the input Domain.
func (r *Repository) DomainCreate(domain *Domain) error { func (r *Repository) DomainCreate(domain *Domain) error {
existDomain, err := r.Domain(domain.Name()) existDomain, err := r.Domain(domain.Name())
@@ -150,6 +205,29 @@ func (r *Repository) DomainCreate(domain *Domain) error {
} }
catchAllUserFile.Close() catchAllUserFile.Close()
if domain.Disabled() {
if err := r.writeDomainDisabledFile(domain.Name(), domain.Disabled()); err != nil {
return err
}
}
return nil
}
// DomainUpdate updates the input Domain.
func (r *Repository) DomainUpdate(domain *Domain) error {
existDomain, err := r.Domain(domain.Name())
if err != nil {
return err
}
if existDomain == nil {
return ErrDomainNotExist
}
if err := r.writeDomainDisabledFile(domain.Name(), domain.Disabled()); err != nil {
return err
}
return nil return nil
} }
@@ -182,3 +260,36 @@ func (r *Repository) DomainRemove(domainName string) error {
return nil return nil
} }
// writeDomainDisabledFile creates/removes the disabled file.
func (r *Repository) writeDomainDisabledFile(domainName string, disabled bool) error {
if !validDomainName(domainName) {
return ErrInvalidDomainName
}
nowDisabled, err := r.domainDisabled(domainName)
if err != nil {
return err
}
domainDisabledFileName := filepath.Join(r.DirMailDataPath, domainName, FileNameDomainDisable)
if !nowDisabled && disabled {
file, err := os.OpenFile(domainDisabledFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
if err := file.Chown(r.uid, r.gid); err != nil {
return err
}
file.Close()
}
if nowDisabled && !disabled {
if err := os.Remove(domainDisabledFileName); err != nil {
return err
}
}
return nil
}

22
glide.lock generated Normal file
View File

@@ -0,0 +1,22 @@
hash: 451657f03f297af9163863497cf6c2f60abfe12d88a282f5aab6deb865d91119
updated: 2016-09-29T12:05:32.00075722+09:00
imports:
- name: github.com/armon/go-radix
version: 4239b77079c7b5d1243b7b4736304ce8ddb6f0f2
- name: github.com/bgentry/speakeasy
version: a1ccbf2c40dfc8ce514b5c5c6e6d1429ea6880da
- name: github.com/BurntSushi/toml
version: 99064174e013895bbd9b025c31100bd1d9b590ca
- name: github.com/jsimonetti/pwscheme
version: 76804708ecad54773871b35dbaa44f517973e395
subpackages:
- ssha
- name: github.com/mattn/go-isatty
version: 66b8e73f3f5cda9f96b69efd03dd3d7fc4a5cdb8
- name: github.com/mitchellh/cli
version: fcf521421aa29bde1d93b6920dfce826d7932208
- name: golang.org/x/sys
version: 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
subpackages:
- unix
testImports: []

7
glide.yaml Normal file
View File

@@ -0,0 +1,7 @@
package: github.com/directorz/mailfull-go
import:
- package: github.com/BurntSushi/toml
- package: github.com/jsimonetti/pwscheme
subpackages:
- ssha
- package: github.com/mitchellh/cli

View File

@@ -34,9 +34,10 @@ var (
ErrAliasUserNotExist = errors.New("AliasUser: not exist") ErrAliasUserNotExist = errors.New("AliasUser: not exist")
ErrAliasUserAlreadyExist = errors.New("AliasUser: already exist") ErrAliasUserAlreadyExist = errors.New("AliasUser: already exist")
ErrInvalidFormatUsersPassword = errors.New("User: password file invalid format") ErrInvalidFormatDomainDisabled = errors.New("Domain: disabled file invalid format")
ErrInvalidFormatAliasDomain = errors.New("AliasDomain: file invalid format") ErrInvalidFormatUsersPassword = errors.New("User: password file invalid format")
ErrInvalidFormatAliasUsers = errors.New("AliasUsers: file invalid format") ErrInvalidFormatAliasDomain = errors.New("AliasDomain: file invalid format")
ErrInvalidFormatAliasUsers = errors.New("AliasUsers: file invalid format")
) )
// RepositoryConfig is used to configure a Repository. // RepositoryConfig is used to configure a Repository.

View File

@@ -1,4 +1,4 @@
package mailfull package mailfull
// Version is a version number. // Version is a version number.
const Version = "v0.0.3" const Version = "v0.0.6"