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

19 Commits

Author SHA1 Message Date
teru
3cf4815565 Merge pull request #20 from directorz/feature/update_golang
Feature/update golang
2016-12-19 13:25:09 +09:00
teru
52e5d32c01 Bump version to v0.0.7 2016-12-19 13:24:41 +09:00
teru
b1d13b49f5 Use golang:1.7.4 2016-12-19 13:24:16 +09:00
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
installdeps:
gom install
glide install -v
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:
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 \
go build -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -v -o "build/mailfull_linux_amd64/mailfull" cmd/mailfull/main.go
-e GOOS=linux -e GOARCH=amd64 golang:1.7.4 \
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:
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 \
go build -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -v -o "build/mailfull_linux_386/mailfull" cmd/mailfull/main.go
-e GOOS=linux -e GOARCH=386 golang:1.7.4 \
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

View File

@@ -16,6 +16,11 @@ Features
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
Installed in `$GOPATH/bin`

View File

@@ -20,7 +20,7 @@ func (c *AliasDomainAddCommand) Synopsis() string {
func (c *AliasDomainAddCommand) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain target
%s %s [-n] domain target
Description:
%s
@@ -30,6 +30,10 @@ Required Args:
The domain name that you want to create.
target
The target domain name.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -39,6 +43,12 @@ Required Args:
// Run runs the command and returns the exit status.
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 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -64,6 +74,10 @@ func (c *AliasDomainAddCommand) Run(args []string) int {
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
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 {
txt := fmt.Sprintf(`
Usage:
%s %s domain
%s %s [-n] domain
Description:
%s
@@ -28,6 +28,10 @@ Description:
Required Args:
domain
The domain name that you want to delete.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -37,6 +41,12 @@ Required Args:
// Run runs the command and returns the exit status.
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 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -55,6 +65,10 @@ func (c *AliasDomainDelCommand) Run(args []string) int {
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
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 {
txt := fmt.Sprintf(`
Usage:
%s %s address target [target...]
%s %s [-n] address target [target...]
Description:
%s
@@ -31,6 +31,10 @@ Required Args:
The email address that you want to create.
target
Target email addresses.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -40,6 +44,12 @@ Required Args:
// Run runs the command and returns the exit status.
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 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -73,6 +83,10 @@ func (c *AliasUserAddCommand) Run(args []string) int {
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
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 {
txt := fmt.Sprintf(`
Usage:
%s %s address
%s %s [-n] address
Description:
%s
@@ -29,6 +29,10 @@ Description:
Required Args:
address
The email address that you want to delete.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -38,6 +42,12 @@ Required Args:
// Run runs the command and returns the exit status.
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 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -63,6 +73,10 @@ func (c *AliasUserDelCommand) Run(args []string) int {
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
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 {
txt := fmt.Sprintf(`
Usage:
%s %s address target [target...]
%s %s [-n] address target [target...]
Description:
%s
@@ -31,6 +31,10 @@ Required Args:
The email address that you want to modify.
target
Target email addresses.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -40,6 +44,12 @@ Required Args:
// Run runs the command and returns the exit status.
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 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -82,6 +92,10 @@ func (c *AliasUserModCommand) Run(args []string) int {
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
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 {
txt := fmt.Sprintf(`
Usage:
%s %s domain user
%s %s [-n] domain user
Description:
%s
@@ -30,6 +30,10 @@ Required Args:
The domain name.
user
The user name that you want to set as catchall user.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -39,6 +43,12 @@ Required Args:
// Run runs the command and returns the exit status.
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 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -64,6 +74,10 @@ func (c *CatchAllSetCommand) Run(args []string) int {
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
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 {
txt := fmt.Sprintf(`
Usage:
%s %s domain
%s %s [-n] domain
Description:
%s
@@ -28,6 +28,10 @@ Description:
Required Args:
domain
The domain name.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -37,6 +41,12 @@ Required Args:
// Run runs the command and returns the exit status.
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 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -55,6 +65,10 @@ func (c *CatchAllUnsetCommand) Run(args []string) int {
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
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 {
txt := fmt.Sprintf(`
Usage:
%s %s domain
%s %s [-n] domain
Description:
%s
@@ -28,6 +28,10 @@ Description:
Required Args:
domain
The domain name that you want to create.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -37,6 +41,12 @@ Required Args:
// Run runs the command and returns the exit status.
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 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -72,6 +82,10 @@ func (c *DomainAddCommand) Run(args []string) int {
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
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 {
txt := fmt.Sprintf(`
Usage:
%s %s domain
%s %s [-n] domain
Description:
%s
@@ -28,6 +28,10 @@ Description:
Required Args:
domain
The domain name that you want to delete.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -37,6 +41,12 @@ Required Args:
// Run runs the command and returns the exit status.
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 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -55,6 +65,10 @@ func (c *DomainDelCommand) Run(args []string) int {
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
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:
%s
Disabled domains are marked "!" the beginning.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -48,7 +49,12 @@ func (c *DomainsCommand) Run(args []string) int {
sort.Sort(mailfull.DomainSlice(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

View File

@@ -1,6 +1,9 @@
package command
import (
"bytes"
"flag"
"github.com/mitchellh/cli"
)
@@ -11,3 +14,17 @@ type Meta struct {
SubCmdName 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 {
txt := fmt.Sprintf(`
Usage:
%s %s address
%s %s [-n] address
Description:
%s
@@ -29,6 +29,10 @@ Description:
Required Args:
address
The email address that you want to create.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -38,6 +42,12 @@ Required Args:
// Run runs the command and returns the exit status.
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 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -70,6 +80,10 @@ func (c *UserAddCommand) Run(args []string) int {
return 1
}
if noCommit {
return 0
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)

View File

@@ -34,7 +34,7 @@ Required Args:
Optional Args:
password
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.Synopsis())

View File

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

View File

@@ -62,6 +62,14 @@ func main() {
meta.SubCmdName = c.Subcommand()
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) {
meta.SubCmdName = c.Subcommand()
return &command.AliasDomainsCommand{Meta: meta}, nil

View File

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

View File

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

121
domain.go
View File

@@ -11,6 +11,7 @@ import (
// Domain represents a Domain.
type Domain struct {
name string
disabled bool
Users []*User
AliasUsers []*AliasUser
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.
func NewDomain(name string) (*Domain, error) {
if !validDomainName(name) {
return nil, ErrInvalidDomainName
}
d := &Domain{}
d := &Domain{
name: name,
if err := d.setName(name); err != nil {
return nil, err
}
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.
func (d *Domain) Name() string {
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.
func (r *Repository) Domains() ([]*Domain, error) {
fileInfos, err := ioutil.ReadDir(r.DirMailDataPath)
@@ -62,6 +82,12 @@ func (r *Repository) Domains() ([]*Domain, error) {
continue
}
disabled, err := r.domainDisabled(name)
if err != nil {
return nil, err
}
domain.SetDisabled(disabled)
domains = append(domains, domain)
}
@@ -94,9 +120,38 @@ func (r *Repository) Domain(domainName string) (*Domain, error) {
return nil, err
}
disabled, err := r.domainDisabled(name)
if err != nil {
return nil, err
}
domain.SetDisabled(disabled)
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.
func (r *Repository) DomainCreate(domain *Domain) error {
existDomain, err := r.Domain(domain.Name())
@@ -150,6 +205,29 @@ func (r *Repository) DomainCreate(domain *Domain) error {
}
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
}
@@ -182,3 +260,36 @@ func (r *Repository) DomainRemove(domainName string) error {
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")
ErrAliasUserAlreadyExist = errors.New("AliasUser: already exist")
ErrInvalidFormatUsersPassword = errors.New("User: password file invalid format")
ErrInvalidFormatAliasDomain = errors.New("AliasDomain: file invalid format")
ErrInvalidFormatAliasUsers = errors.New("AliasUsers: file invalid format")
ErrInvalidFormatDomainDisabled = errors.New("Domain: disabled file invalid format")
ErrInvalidFormatUsersPassword = errors.New("User: password file invalid format")
ErrInvalidFormatAliasDomain = errors.New("AliasDomain: file invalid format")
ErrInvalidFormatAliasUsers = errors.New("AliasUsers: file invalid format")
)
// RepositoryConfig is used to configure a Repository.

View File

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