1
0
mirror of https://github.com/directorz/mailfull-go.git synced 2025-12-19 18:47:05 +00:00

52 Commits

Author SHA1 Message Date
bambi919
5d2183e030 Update README.md 2019-04-25 16:22:05 +09:00
bambi919
3bd25102e4 Create commands_guide_ja.md 2019-04-25 16:20:32 +09:00
teru
624579aed5 Merge pull request #42 from directorz/release/v1.0.3
Release/v1.0.3
2018-03-16 12:20:52 +09:00
teru
0f0a3835fc Bump up version to v1.0.3 2018-03-16 12:19:53 +09:00
teru
a145712856 Update vendor packages 2018-03-16 12:19:38 +09:00
teru
ad18a41b64 Merge pull request #41 from directorz/feature/fix_removed_user
Feature/fix removed user
2018-03-16 12:17:15 +09:00
teru
ac6a8526b1 Fix userlist 2018-03-16 12:16:05 +09:00
teru
067c8f6903 Merge pull request #40 from directorz/feature/build
Feature/build
2018-03-16 11:29:35 +09:00
teru
e7254c6df6 Use internal ghr command 2018-03-16 11:27:48 +09:00
teru
8ecd1f0f79 Update go to 1.10 2018-03-16 11:07:40 +09:00
teru
de6ddf7e1b Simplify PHONY targets 2018-03-16 11:06:59 +09:00
teru
58b508b7fa Merge pull request #39 from directorz/release/v1.0.2
Release/v1.0.2
2017-12-13 15:24:10 +09:00
teru
36f6eb22d2 Merge pull request #38 from directorz/release/v1.0.2
Release/v1.0.2
2017-12-13 15:23:25 +09:00
teru
78ba1d2674 Bump version to v1.0.2 2017-12-13 15:22:57 +09:00
teru
b4461b66ca Updated go version: 1.9.2 2017-12-13 15:22:25 +09:00
teru
afb8e4eaf4 Merge pull request #37 from directorz/release/v1.0.1
Release/v1.0.1
2017-12-13 15:17:58 +09:00
teru
4c9781ad71 Merge pull request #36 from directorz/release/v1.0.1
Release/v1.0.1
2017-12-13 15:17:27 +09:00
teru
e32523d0b2 Bump version to v1.0.1 2017-12-13 15:16:35 +09:00
teru
188be4c3e8 Update libraries 2017-12-13 15:15:54 +09:00
teru
de4bddc161 Merge pull request #35 from directorz/feature/dep_flag
Added `-vendor-only` flag
2017-12-13 15:13:05 +09:00
teru
f618eb24e6 Added -vendor-only flag 2017-12-13 15:12:07 +09:00
teru
096193d93d Merge pull request #34 from directorz/feature/show_runtime_version
Now show runtime version in `mailfull --version`
2017-12-13 15:11:23 +09:00
teru
e32ed61771 Now show runtime version in mailfull --version 2017-12-13 15:07:44 +09:00
teru
3ae4d8d590 Merge pull request #30 from directorz/feature/v1.0.0
Feature/v1.0.0
2017-07-25 13:05:27 +09:00
teru
d4343eacce Merge pull request #29 from directorz/feature/bump_version
Bump version to v1.0.0
2017-07-25 13:05:04 +09:00
teru
a97a9e343b Bump version to v1.0.0 2017-07-25 13:04:25 +09:00
teru
f61d18f31f Merge pull request #28 from directorz/feature/remove_type_maildata
Remove type MailData
2017-07-25 13:02:30 +09:00
teru
9c92ac9656 Remove type MailData 2017-07-25 12:48:54 +09:00
teru
30f0279751 Merge pull request #27 from directorz/feature/remove_types_for_sort
Remove types for sort.Interface #26
2017-07-25 12:31:39 +09:00
teru
c7e56f26af Remove types for sort.Interface 2017-07-25 12:29:23 +09:00
teru
58b50cb3f6 Merge pull request #25 from directorz/feature/flatten
Feature/flatten
2017-07-25 11:58:26 +09:00
teru
146ab299d0 Use Errorf 2017-07-25 11:57:30 +09:00
teru
2e87209ad2 Move Meta to cmd package 2017-07-25 11:40:51 +09:00
teru
5a178c350b Change structs name 2017-07-25 11:35:42 +09:00
teru
b884655a7c Renamed 2017-07-25 11:22:11 +09:00
teru
552ed95a0f Integrate subpackage 2017-07-25 11:19:25 +09:00
teru
2bb46731d0 Merge pull request #24 from directorz/feature/cosme
cosmetic
2017-07-25 11:06:30 +09:00
teru
5a64a543ca cosmetic 2017-07-25 11:05:28 +09:00
teru
d0dd68e2b6 Merge pull request #23 from directorz/feature/build
Feature/build
2017-07-25 11:03:49 +09:00
teru
1daea44e49 Use golang:1.8.3 2017-07-25 11:01:55 +09:00
teru
3ac5856917 Use golang/dep instead of glide #21 2017-07-25 10:43:07 +09:00
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
42 changed files with 987 additions and 591 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'

74
Gopkg.lock generated Normal file
View File

@@ -0,0 +1,74 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/BurntSushi/toml"
packages = ["."]
revision = "b26d9c308763d68093482582cea63d69be07a0f0"
version = "v0.3.0"
[[projects]]
branch = "master"
name = "github.com/armon/go-radix"
packages = ["."]
revision = "1fca145dffbcaa8fe914309b1ec0cfc67500fe61"
[[projects]]
name = "github.com/bgentry/speakeasy"
packages = ["."]
revision = "4aabc24848ce5fd31929f7d1e4ea74d3709c14cd"
version = "v0.1.0"
[[projects]]
branch = "master"
name = "github.com/hashicorp/errwrap"
packages = ["."]
revision = "7554cd9344cec97297fa6649b055a8c98c2a1e55"
[[projects]]
branch = "master"
name = "github.com/hashicorp/go-multierror"
packages = ["."]
revision = "b7773ae218740a7be65057fc60b366a49b538a44"
[[projects]]
branch = "master"
name = "github.com/jsimonetti/pwscheme"
packages = ["ssha"]
revision = "76804708ecad54773871b35dbaa44f517973e395"
[[projects]]
name = "github.com/mattn/go-isatty"
packages = ["."]
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
version = "v0.0.3"
[[projects]]
branch = "master"
name = "github.com/mitchellh/cli"
packages = ["."]
revision = "518dc677a1e1222682f4e7db06721942cb8e9e4c"
[[projects]]
name = "github.com/posener/complete"
packages = [
".",
"cmd",
"cmd/install",
"match"
]
revision = "98eb9847f27ba2008d380a32c98be474dea55bdf"
version = "v1.1.1"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["unix"]
revision = "cc7307a45468e49eaf2997c890f14aa03a26917b"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "d88d2668ae10b500606e3ebb1e719897e62e423f5ede8e4b470d12c1d255fe31"
solver-name = "gps-cdcl"
solver-version = 1

0
Gopkg.toml Normal file
View File

View File

@@ -1,29 +1,53 @@
GOVERSION=$(shell go version)
GOOS=$(word 1,$(subst /, ,$(lastword $(GOVERSION))))
GOARCH=$(word 2,$(subst /, ,$(lastword $(GOVERSION))))
THIS_GOOS=$(word 1,$(subst /, ,$(lastword $(GOVERSION))))
THIS_GOARCH=$(word 2,$(subst /, ,$(lastword $(GOVERSION))))
GOOS?=$(THIS_GOOS)
GOARCH?=$(THIS_GOARCH)
DIR_PKG=$(subst /src/github.com/directorz/mailfull-go,/pkg,$(PWD))
DIR_BUILD=build
DIR_RELEASE=release
VERSION=$(patsubst "%",%,$(lastword $(shell grep 'const Version' version.go)))
.PHONY: build build-linux-amd64 build-linux-386 clean
GITTAG=$(shell git rev-parse --short HEAD)
default: build
installdeps:
gom install
FORCE:
.PHONY: FORCE
build:
go build -v -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -o build/mailfull_$(GOOS)_$(GOARCH)/mailfull cmd/mailfull/mailfull.go
$(DIR_BUILD)/bin/$(THIS_GOOS)_$(THIS_GOARCH)/dep:
mkdir -p /tmp/go
GOPATH=/tmp/go go get -d -v github.com/golang/dep
GOPATH=/tmp/go go build -v -o $(DIR_BUILD)/bin/$(THIS_GOOS)_$(THIS_GOARCH)/dep github.com/golang/dep/cmd/dep
rm -rf /tmp/go
dep: $(DIR_BUILD)/bin/$(THIS_GOOS)_$(THIS_GOARCH)/dep
$(DIR_BUILD)/bin/$(THIS_GOOS)_$(THIS_GOARCH)/ghr:
mkdir -p /tmp/go
GOPATH=/tmp/go go get -d -v github.com/tcnksm/ghr
GOPATH=/tmp/go go build -v -o $(DIR_BUILD)/bin/$(THIS_GOOS)_$(THIS_GOARCH)/ghr github.com/tcnksm/ghr
rm -rf /tmp/go
ghr: $(DIR_BUILD)/bin/$(THIS_GOOS)_$(THIS_GOARCH)/ghr
installdeps: dep
$(DIR_BUILD)/bin/$(THIS_GOOS)_$(THIS_GOARCH)/dep ensure -v -vendor-only
build: FORCE
go build -v -ldflags "-X main.gittag=$(GITTAG)" -o $(DIR_BUILD)/mailfull_$(GOOS)_$(GOARCH)/mailfull cmd/mailfull/*.go
.build-docker:
docker run --rm -v $(DIR_PKG):/go/pkg -v $(PWD):/go/src/github.com/directorz/mailfull-go -w /go/src/github.com/directorz/mailfull-go \
-e GOOS=$(GOOS) -e GOARCH=$(GOARCH) golang:1.10 \
go build -v -ldflags "-X main.gittag=$(GITTAG)" -o $(DIR_BUILD)/mailfull_$(GOOS)_$(GOARCH)/mailfull cmd/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 -v -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -o "build/mailfull_linux_amd64/mailfull" cmd/mailfull/mailfull.go
@$(MAKE) .build-docker GOOS=linux GOARCH=amd64
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 -v -ldflags "-X main.gittag=`git rev-parse --short HEAD`" -o "build/mailfull_linux_386/mailfull" cmd/mailfull/mailfull.go
@$(MAKE) .build-docker GOOS=linux GOARCH=386
release: release-linux-amd64 release-linux-386
@@ -42,12 +66,13 @@ release-targz: dir-$(DIR_RELEASE)
dir-$(DIR_RELEASE):
mkdir -p $(DIR_RELEASE)
release-upload: release-linux-amd64 release-linux-386 release-github-token
ghr -u directorz -r mailfull-go -t $(shell cat github_token) --replace --draft $(VERSION) $(DIR_RELEASE)
release-upload: ghr release-linux-amd64 release-linux-386 release-github-token
$(DIR_BUILD)/bin/$(THIS_GOOS)_$(THIS_GOARCH)/ghr -u directorz -r mailfull-go -t $(shell cat github_token) --replace --draft $(VERSION) $(DIR_RELEASE)
release-github-token: github_token
@echo "file \"github_token\" is required"
clean:
-rm -rf $(DIR_BUILD)
-rm -rf $(DIR_RELEASE)

View File

@@ -15,13 +15,6 @@ type AliasDomain struct {
target string
}
// AliasDomainSlice attaches the methods of sort.Interface to []*AliasDomain.
type AliasDomainSlice []*AliasDomain
func (p AliasDomainSlice) Len() int { return len(p) }
func (p AliasDomainSlice) Less(i, j int) bool { return p[i].Name() < p[j].Name() }
func (p AliasDomainSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// NewAliasDomain creates a new AliasDomain instance.
func NewAliasDomain(name, target string) (*AliasDomain, error) {
ad := &AliasDomain{}
@@ -190,7 +183,7 @@ func (r *Repository) writeAliasDomainsFile(aliasDomains []*AliasDomain) error {
}
defer file.Close()
sort.Sort(AliasDomainSlice(aliasDomains))
sort.Slice(aliasDomains, func(i, j int) bool { return aliasDomains[i].Name() < aliasDomains[j].Name() })
for _, aliasDomain := range aliasDomains {
if _, err := fmt.Fprintf(file, "%s:%s\n", aliasDomain.Name(), aliasDomain.Target()); err != nil {

View File

@@ -21,13 +21,6 @@ type AliasUser struct {
targets []string
}
// AliasUserSlice attaches the methods of sort.Interface to []*AliasUser.
type AliasUserSlice []*AliasUser
func (p AliasUserSlice) Len() int { return len(p) }
func (p AliasUserSlice) Less(i, j int) bool { return p[i].Name() < p[j].Name() }
func (p AliasUserSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// NewAliasUser creates a new AliasUser instance.
func NewAliasUser(name string, targets []string) (*AliasUser, error) {
au := &AliasUser{}
@@ -233,7 +226,7 @@ func (r *Repository) writeAliasUsersFile(domainName string, aliasUsers []*AliasU
}
defer file.Close()
sort.Sort(AliasUserSlice(aliasUsers))
sort.Slice(aliasUsers, func(i, j int) bool { return aliasUsers[i].Name() < aliasUsers[j].Name() })
for _, aliasUser := range aliasUsers {
if _, err := fmt.Fprintf(file, "%s:%s\n", aliasUser.Name(), strings.Join(aliasUser.Targets(), ",")); err != nil {

View File

@@ -1,26 +1,27 @@
package command
package main
import (
"fmt"
mailfull "github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// AliasDomainAddCommand represents a AliasDomainAddCommand.
type AliasDomainAddCommand struct {
Meta
// CmdAliasDomainAdd represents a CmdAliasDomainAdd.
type CmdAliasDomainAdd struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *AliasDomainAddCommand) Synopsis() string {
func (c *CmdAliasDomainAdd) Synopsis() string {
return "Create a new aliasdomain."
}
// Help returns long-form help text.
func (c *AliasDomainAddCommand) Help() string {
func (c *CmdAliasDomainAdd) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain target
%s %s [-n] domain target
Description:
%s
@@ -30,6 +31,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())
@@ -38,7 +43,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *AliasDomainAddCommand) Run(args []string) int {
func (c *CmdAliasDomainAdd) 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
@@ -49,30 +60,26 @@ func (c *AliasDomainAddCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
aliasDomain, err := mailfull.NewAliasDomain(aliasDomainName, targetDomainName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.AliasDomainCreate(aliasDomain); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,26 +1,27 @@
package command
package main
import (
"fmt"
mailfull "github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// AliasDomainDelCommand represents a AliasDomainDelCommand.
type AliasDomainDelCommand struct {
Meta
// CmdAliasDomainDel represents a CmdAliasDomainDel.
type CmdAliasDomainDel struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *AliasDomainDelCommand) Synopsis() string {
func (c *CmdAliasDomainDel) Synopsis() string {
return "Delete a aliasdomain."
}
// Help returns long-form help text.
func (c *AliasDomainDelCommand) Help() string {
func (c *CmdAliasDomainDel) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain
%s %s [-n] domain
Description:
%s
@@ -28,6 +29,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())
@@ -36,7 +41,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *AliasDomainDelCommand) Run(args []string) int {
func (c *CmdAliasDomainDel) 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
@@ -46,24 +57,20 @@ func (c *AliasDomainDelCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.AliasDomainRemove(aliasDomainName); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,24 +1,25 @@
package command
package main
import (
"fmt"
"sort"
mailfull "github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// AliasDomainsCommand represents a AliasDomainsCommand.
type AliasDomainsCommand struct {
Meta
// CmdAliasDomains represents a CmdAliasDomains.
type CmdAliasDomains struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *AliasDomainsCommand) Synopsis() string {
func (c *CmdAliasDomains) Synopsis() string {
return "Show aliasdomains."
}
// Help returns long-form help text.
func (c *AliasDomainsCommand) Help() string {
func (c *CmdAliasDomains) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s [domain]
@@ -37,7 +38,7 @@ Optional Args:
}
// Run runs the command and returns the exit status.
func (c *AliasDomainsCommand) Run(args []string) int {
func (c *CmdAliasDomains) Run(args []string) int {
if len(args) > 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -50,16 +51,16 @@ func (c *AliasDomainsCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
aliasDomains, err := repo.AliasDomains()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
sort.Sort(mailfull.AliasDomainSlice(aliasDomains))
sort.Slice(aliasDomains, func(i, j int) bool { return aliasDomains[i].Name() < aliasDomains[j].Name() })
for _, aliasDomain := range aliasDomains {
if targetDomainName != "" {

View File

@@ -1,27 +1,28 @@
package command
package main
import (
"fmt"
"strings"
mailfull "github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// AliasUserAddCommand represents a AliasUserAddCommand.
type AliasUserAddCommand struct {
Meta
// CmdAliasUserAdd represents a CmdAliasUserAdd.
type CmdAliasUserAdd struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *AliasUserAddCommand) Synopsis() string {
func (c *CmdAliasUserAdd) Synopsis() string {
return "Create a new aliasuser."
}
// Help returns long-form help text.
func (c *AliasUserAddCommand) Help() string {
func (c *CmdAliasUserAdd) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s address target [target...]
%s %s [-n] address target [target...]
Description:
%s
@@ -31,6 +32,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())
@@ -39,7 +44,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *AliasUserAddCommand) Run(args []string) int {
func (c *CmdAliasUserAdd) 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
@@ -58,30 +69,26 @@ func (c *AliasUserAddCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
aliasUser, err := mailfull.NewAliasUser(aliasUserName, targets)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.AliasUserCreate(domainName, aliasUser); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,27 +1,28 @@
package command
package main
import (
"fmt"
"strings"
mailfull "github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// AliasUserDelCommand represents a AliasUserDelCommand.
type AliasUserDelCommand struct {
Meta
// CmdAliasUserDel represents a CmdAliasUserDel.
type CmdAliasUserDel struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *AliasUserDelCommand) Synopsis() string {
func (c *CmdAliasUserDel) Synopsis() string {
return "Delete a aliasuser."
}
// Help returns long-form help text.
func (c *AliasUserDelCommand) Help() string {
func (c *CmdAliasUserDel) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s address
%s %s [-n] address
Description:
%s
@@ -29,6 +30,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())
@@ -37,7 +42,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *AliasUserDelCommand) Run(args []string) int {
func (c *CmdAliasUserDel) 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
@@ -54,24 +65,20 @@ func (c *AliasUserDelCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.AliasUserRemove(domainName, aliasUserName); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,27 +1,28 @@
package command
package main
import (
"fmt"
"strings"
mailfull "github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// AliasUserModCommand represents a AliasUserModCommand.
type AliasUserModCommand struct {
Meta
// CmdAliasUserMod represents a CmdAliasUserMod.
type CmdAliasUserMod struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *AliasUserModCommand) Synopsis() string {
func (c *CmdAliasUserMod) Synopsis() string {
return "Modify a aliasuser."
}
// Help returns long-form help text.
func (c *AliasUserModCommand) Help() string {
func (c *CmdAliasUserMod) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s address target [target...]
%s %s [-n] address target [target...]
Description:
%s
@@ -31,6 +32,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())
@@ -39,7 +44,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *AliasUserModCommand) Run(args []string) int {
func (c *CmdAliasUserMod) 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
@@ -58,39 +69,35 @@ func (c *AliasUserModCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
aliasUser, err := repo.AliasUser(domainName, aliasUserName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if aliasUser == nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", mailfull.ErrAliasUserNotExist)
c.Meta.Errorf("%v\n", mailfull.ErrAliasUserNotExist)
return 1
}
if err := aliasUser.SetTargets(targets); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.AliasUserUpdate(domainName, aliasUser); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,24 +1,25 @@
package command
package main
import (
"fmt"
"sort"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// AliasUsersCommand represents a AliasUsersCommand.
type AliasUsersCommand struct {
Meta
// CmdAliasUsers represents a CmdAliasUsers.
type CmdAliasUsers struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *AliasUsersCommand) Synopsis() string {
func (c *CmdAliasUsers) Synopsis() string {
return "Show aliasusers."
}
// Help returns long-form help text.
func (c *AliasUsersCommand) Help() string {
func (c *CmdAliasUsers) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain
@@ -37,7 +38,7 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *AliasUsersCommand) Run(args []string) int {
func (c *CmdAliasUsers) Run(args []string) int {
if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -47,16 +48,16 @@ func (c *AliasUsersCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
aliasUsers, err := repo.AliasUsers(targetDomainName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
sort.Sort(mailfull.AliasUserSlice(aliasUsers))
sort.Slice(aliasUsers, func(i, j int) bool { return aliasUsers[i].Name() < aliasUsers[j].Name() })
for _, aliasUser := range aliasUsers {
fmt.Fprintf(c.UI.Writer, "%s\n", aliasUser.Name())

View File

@@ -1,23 +1,24 @@
package command
package main
import (
"fmt"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// CatchAllCommand represents a CatchAllCommand.
type CatchAllCommand struct {
Meta
// CmdCatchAll represents a CmdCatchAll.
type CmdCatchAll struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *CatchAllCommand) Synopsis() string {
func (c *CmdCatchAll) Synopsis() string {
return "Show a catchall user."
}
// Help returns long-form help text.
func (c *CatchAllCommand) Help() string {
func (c *CmdCatchAll) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain
@@ -36,7 +37,7 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *CatchAllCommand) Run(args []string) int {
func (c *CmdCatchAll) Run(args []string) int {
if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -46,13 +47,13 @@ func (c *CatchAllCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
catchAllUser, err := repo.CatchAllUser(domainName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,26 +1,27 @@
package command
package main
import (
"fmt"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// CatchAllSetCommand represents a CatchAllSetCommand.
type CatchAllSetCommand struct {
Meta
// CmdCatchAllSet represents a CmdCatchAllSet.
type CmdCatchAllSet struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *CatchAllSetCommand) Synopsis() string {
func (c *CmdCatchAllSet) Synopsis() string {
return "Set a catchall user."
}
// Help returns long-form help text.
func (c *CatchAllSetCommand) Help() string {
func (c *CmdCatchAllSet) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain user
%s %s [-n] domain user
Description:
%s
@@ -30,6 +31,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())
@@ -38,7 +43,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *CatchAllSetCommand) Run(args []string) int {
func (c *CmdCatchAllSet) 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
@@ -49,30 +60,26 @@ func (c *CatchAllSetCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
catchAllUser, err := mailfull.NewCatchAllUser(userName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.CatchAllUserSet(domainName, catchAllUser); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,26 +1,27 @@
package command
package main
import (
"fmt"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// CatchAllUnsetCommand represents a CatchAllUnsetCommand.
type CatchAllUnsetCommand struct {
Meta
// CmdCatchAllUnset represents a CmdCatchAllUnset.
type CmdCatchAllUnset struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *CatchAllUnsetCommand) Synopsis() string {
func (c *CmdCatchAllUnset) Synopsis() string {
return "Unset a catchall user."
}
// Help returns long-form help text.
func (c *CatchAllUnsetCommand) Help() string {
func (c *CmdCatchAllUnset) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain
%s %s [-n] domain
Description:
%s
@@ -28,6 +29,10 @@ Description:
Required Args:
domain
The domain name.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -36,7 +41,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *CatchAllUnsetCommand) Run(args []string) int {
func (c *CmdCatchAllUnset) 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
@@ -46,24 +57,20 @@ func (c *CatchAllUnsetCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.CatchAllUserUnset(domainName); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -0,0 +1,49 @@
package main
import (
"fmt"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// CmdCommit represents a CmdCommit.
type CmdCommit struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *CmdCommit) Synopsis() string {
return "Create databases from the structure of the MailData directory."
}
// Help returns long-form help text.
func (c *CmdCommit) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s
Description:
%s
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
return txt[1:]
}
// Run runs the command and returns the exit status.
func (c *CmdCommit) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}
return 0
}

View File

@@ -1,26 +1,27 @@
package command
package main
import (
"fmt"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// DomainAddCommand represents a DomainAddCommand.
type DomainAddCommand struct {
Meta
// CmdDomainAdd represents a CmdDomainAdd.
type CmdDomainAdd struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *DomainAddCommand) Synopsis() string {
func (c *CmdDomainAdd) Synopsis() string {
return "Create a new domain and postmaster."
}
// Help returns long-form help text.
func (c *DomainAddCommand) Help() string {
func (c *CmdDomainAdd) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain
%s %s [-n] domain
Description:
%s
@@ -28,6 +29,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())
@@ -36,7 +41,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *DomainAddCommand) Run(args []string) int {
func (c *CmdDomainAdd) 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
@@ -46,41 +57,37 @@ func (c *DomainAddCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
domain, err := mailfull.NewDomain(domainName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.DomainCreate(domain); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
user, err := mailfull.NewUser("postmaster", mailfull.NeverMatchHashedPassword, nil)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.UserCreate(domainName, user); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,26 +1,27 @@
package command
package main
import (
"fmt"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// DomainDelCommand represents a DomainDelCommand.
type DomainDelCommand struct {
Meta
// CmdDomainDel represents a CmdDomainDel.
type CmdDomainDel struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *DomainDelCommand) Synopsis() string {
func (c *CmdDomainDel) Synopsis() string {
return "Delete and backup a domain."
}
// Help returns long-form help text.
func (c *DomainDelCommand) Help() string {
func (c *CmdDomainDel) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain
%s %s [-n] domain
Description:
%s
@@ -28,6 +29,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())
@@ -36,7 +41,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *DomainDelCommand) Run(args []string) int {
func (c *CmdDomainDel) 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
@@ -46,24 +57,20 @@ func (c *DomainDelCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.DomainRemove(domainName); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,26 +1,27 @@
package command
package main
import (
"fmt"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// DomainDisableCommand represents a DomainDisableCommand.
type DomainDisableCommand struct {
Meta
// CmdDomainDisable represents a CmdDomainDisable.
type CmdDomainDisable struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *DomainDisableCommand) Synopsis() string {
func (c *CmdDomainDisable) Synopsis() string {
return "Disable a domain temporarily."
}
// Help returns long-form help text.
func (c *DomainDisableCommand) Help() string {
func (c *CmdDomainDisable) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain
%s %s [-n] domain
Description:
%s
@@ -28,6 +29,10 @@ Description:
Required Args:
domain
The domain name that you want to disable.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -36,7 +41,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *DomainDisableCommand) Run(args []string) int {
func (c *CmdDomainDisable) 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
@@ -46,36 +57,32 @@ func (c *DomainDisableCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
domain, err := repo.Domain(domainName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if domain == nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", mailfull.ErrDomainNotExist)
c.Meta.Errorf("%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)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,26 +1,27 @@
package command
package main
import (
"fmt"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// DomainEnableCommand represents a DomainEnableCommand.
type DomainEnableCommand struct {
Meta
// CmdDomainEnable represents a CmdDomainEnable.
type CmdDomainEnable struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *DomainEnableCommand) Synopsis() string {
func (c *CmdDomainEnable) Synopsis() string {
return "Enable a domain."
}
// Help returns long-form help text.
func (c *DomainEnableCommand) Help() string {
func (c *CmdDomainEnable) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain
%s %s [-n] domain
Description:
%s
@@ -28,6 +29,10 @@ Description:
Required Args:
domain
The domain name that you want to enable.
Optional Args:
-n
Don't update databases.
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
@@ -36,7 +41,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *DomainEnableCommand) Run(args []string) int {
func (c *CmdDomainEnable) 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
@@ -46,36 +57,32 @@ func (c *DomainEnableCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
domain, err := repo.Domain(domainName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if domain == nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", mailfull.ErrDomainNotExist)
c.Meta.Errorf("%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)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,24 +1,25 @@
package command
package main
import (
"fmt"
"sort"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// DomainsCommand represents a DomainsCommand.
type DomainsCommand struct {
Meta
// CmdDomains represents a CmdDomains.
type CmdDomains struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *DomainsCommand) Synopsis() string {
func (c *CmdDomains) Synopsis() string {
return "Show domains."
}
// Help returns long-form help text.
func (c *DomainsCommand) Help() string {
func (c *CmdDomains) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s
@@ -34,19 +35,19 @@ Description:
}
// Run runs the command and returns the exit status.
func (c *DomainsCommand) Run(args []string) int {
func (c *CmdDomains) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
domains, err := repo.Domains()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
sort.Sort(mailfull.DomainSlice(domains))
sort.Slice(domains, func(i, j int) bool { return domains[i].Name() < domains[j].Name() })
for _, domain := range domains {
disableStr := ""

View File

@@ -1,23 +1,24 @@
package command
package main
import (
"fmt"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// GenConfigCommand represents a GenConfigCommand.
type GenConfigCommand struct {
Meta
// CmdGenConfig represents a CmdGenConfig.
type CmdGenConfig struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *GenConfigCommand) Synopsis() string {
func (c *CmdGenConfig) Synopsis() string {
return "Write a Postfix or Dovecot configuration to stdout."
}
// Help returns long-form help text.
func (c *GenConfigCommand) Help() string {
func (c *CmdGenConfig) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s name
@@ -37,7 +38,7 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *GenConfigCommand) Run(args []string) int {
func (c *CmdGenConfig) Run(args []string) int {
if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -47,7 +48,7 @@ func (c *GenConfigCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
@@ -59,7 +60,7 @@ func (c *GenConfigCommand) Run(args []string) int {
fmt.Fprintf(c.UI.Writer, "%s", repo.GenerateConfigDovecot())
default:
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] Specify \"postfix\" or \"dovecot\".\n")
c.Meta.Errorf("Specify \"postfix\" or \"dovecot\".\n")
return 1
}

View File

@@ -1,23 +1,24 @@
package command
package main
import (
"fmt"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// InitCommand represents a InitCommand.
type InitCommand struct {
Meta
// CmdInit represents a CmdInit.
type CmdInit struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *InitCommand) Synopsis() string {
func (c *CmdInit) Synopsis() string {
return "Initializes current directory as a Mailfull repository."
}
// Help returns long-form help text.
func (c *InitCommand) Help() string {
func (c *CmdInit) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s
@@ -32,9 +33,9 @@ Description:
}
// Run runs the command and returns the exit status.
func (c *InitCommand) Run(args []string) int {
func (c *CmdInit) Run(args []string) int {
if err := mailfull.InitRepository("."); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,27 +1,28 @@
package command
package main
import (
"fmt"
"strings"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// UserAddCommand represents a UserAddCommand.
type UserAddCommand struct {
Meta
// CmdUserAdd represents a CmdUserAdd.
type CmdUserAdd struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *UserAddCommand) Synopsis() string {
func (c *CmdUserAdd) Synopsis() string {
return "Create a new user."
}
// Help returns long-form help text.
func (c *UserAddCommand) Help() string {
func (c *CmdUserAdd) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s address
%s %s [-n] address
Description:
%s
@@ -29,6 +30,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())
@@ -37,7 +42,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *UserAddCommand) Run(args []string) int {
func (c *CmdUserAdd) 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,30 +66,26 @@ func (c *UserAddCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
user, err := mailfull.NewUser(userName, mailfull.NeverMatchHashedPassword, nil)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if err := repo.UserCreate(domainName, user); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,25 +1,26 @@
package command
package main
import (
"fmt"
"strings"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
"github.com/jsimonetti/pwscheme/ssha"
)
// UserCheckPwCommand represents a UserCheckPwCommand.
type UserCheckPwCommand struct {
Meta
// CmdUserCheckPw represents a CmdUserCheckPw.
type CmdUserCheckPw struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *UserCheckPwCommand) Synopsis() string {
func (c *CmdUserCheckPw) Synopsis() string {
return "Check user's password."
}
// Help returns long-form help text.
func (c *UserCheckPwCommand) Help() string {
func (c *CmdUserCheckPw) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s address [password]
@@ -34,7 +35,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())
@@ -43,7 +44,7 @@ Optional Args:
}
// Run runs the command and returns the exit status.
func (c *UserCheckPwCommand) Run(args []string) int {
func (c *CmdUserCheckPw) Run(args []string) int {
if len(args) != 1 && len(args) != 2 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -66,24 +67,24 @@ func (c *UserCheckPwCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
user, err := repo.User(domainName, userName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if user == nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", mailfull.ErrUserNotExist)
c.Meta.Errorf("%v\n", mailfull.ErrUserNotExist)
return 1
}
if len(args) != 2 {
input, err := c.UI.AskSecret(fmt.Sprintf("Enter password for %s:", address))
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,27 +1,28 @@
package command
package main
import (
"fmt"
"strings"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// UserDelCommand represents a UserDelCommand.
type UserDelCommand struct {
Meta
// CmdUserDel represents a CmdUserDel.
type CmdUserDel struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *UserDelCommand) Synopsis() string {
func (c *CmdUserDel) Synopsis() string {
return "Delete and backup a user."
}
// Help returns long-form help text.
func (c *UserDelCommand) Help() string {
func (c *CmdUserDel) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s address
%s %s [-n] address
Description:
%s
@@ -29,6 +30,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())
@@ -37,7 +42,13 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *UserDelCommand) Run(args []string) int {
func (c *CmdUserDel) 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,29 +66,25 @@ func (c *UserDelCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if userName == "postmaster" {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] Cannot delete postmaster.\n")
c.Meta.Errorf("Cannot delete postmaster.\n")
return 1
}
if err := repo.UserRemove(domainName, userName); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,28 +1,29 @@
package command
package main
import (
"fmt"
"strings"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
"github.com/jsimonetti/pwscheme/ssha"
)
// UserPasswdCommand represents a UserPasswdCommand.
type UserPasswdCommand struct {
Meta
// CmdUserPasswd represents a CmdUserPasswd.
type CmdUserPasswd struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *UserPasswdCommand) Synopsis() string {
func (c *CmdUserPasswd) Synopsis() string {
return "Update user's password."
}
// Help returns long-form help text.
func (c *UserPasswdCommand) Help() string {
func (c *CmdUserPasswd) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s address [password]
%s %s [-n] address [password]
Description:
%s
@@ -32,9 +33,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())
@@ -43,7 +46,13 @@ Optional Args:
}
// Run runs the command and returns the exit status.
func (c *UserPasswdCommand) Run(args []string) int {
func (c *CmdUserPasswd) 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
@@ -66,33 +75,33 @@ func (c *UserPasswdCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
user, err := repo.User(domainName, userName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if user == nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", mailfull.ErrUserNotExist)
c.Meta.Errorf("%v\n", mailfull.ErrUserNotExist)
return 1
}
if len(args) != 2 {
input1, err := c.UI.AskSecret(fmt.Sprintf("Enter new password for %s:", address))
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
input2, err := c.UI.AskSecret("Retype new password:")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
if input1 != input2 {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] inputs do not match.\n")
c.Meta.Errorf("inputs do not match.\n")
return 1
}
rawPassword = input1
@@ -102,7 +111,7 @@ func (c *UserPasswdCommand) Run(args []string) int {
if rawPassword != "" {
str, err := ssha.Generate(rawPassword, 4)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
hashedPassword = str
@@ -111,19 +120,15 @@ func (c *UserPasswdCommand) Run(args []string) int {
user.SetHashedPassword(hashedPassword)
if err := repo.UserUpdate(domainName, user); err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
mailData, err := repo.MailData()
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
if noCommit {
return 0
}
err = repo.GenerateDatabases(mailData)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
if err = repo.GenerateDatabases(); err != nil {
c.Meta.Errorf("%v\n", err)
return 1
}

View File

@@ -1,24 +1,25 @@
package command
package main
import (
"fmt"
"sort"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd"
)
// UsersCommand represents a UsersCommand.
type UsersCommand struct {
Meta
// CmdUsers represents a CmdUsers.
type CmdUsers struct {
cmd.Meta
}
// Synopsis returns a one-line synopsis.
func (c *UsersCommand) Synopsis() string {
func (c *CmdUsers) Synopsis() string {
return "Show users."
}
// Help returns long-form help text.
func (c *UsersCommand) Help() string {
func (c *CmdUsers) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s domain
@@ -37,7 +38,7 @@ Required Args:
}
// Run runs the command and returns the exit status.
func (c *UsersCommand) Run(args []string) int {
func (c *CmdUsers) Run(args []string) int {
if len(args) != 1 {
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
return 1
@@ -47,16 +48,16 @@ func (c *UsersCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
users, err := repo.Users(targetDomainName)
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
c.Meta.Errorf("%v\n", err)
return 1
}
sort.Sort(mailfull.UserSlice(users))
sort.Slice(users, func(i, j int) bool { return users[i].Name() < users[j].Name() })
for _, user := range users {
fmt.Fprintf(c.UI.Writer, "%s\n", user.Name())

View File

@@ -1,55 +0,0 @@
package command
import (
"fmt"
"github.com/directorz/mailfull-go"
)
// CommitCommand represents a CommitCommand.
type CommitCommand struct {
Meta
}
// Synopsis returns a one-line synopsis.
func (c *CommitCommand) Synopsis() string {
return "Create databases from the structure of the MailData directory."
}
// Help returns long-form help text.
func (c *CommitCommand) Help() string {
txt := fmt.Sprintf(`
Usage:
%s %s
Description:
%s
`,
c.CmdName, c.SubCmdName,
c.Synopsis())
return txt[1:]
}
// Run runs the command and returns the exit status.
func (c *CommitCommand) Run(args []string) int {
repo, err := mailfull.OpenRepository(".")
if err != nil {
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
return 1
}
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

@@ -1,13 +0,0 @@
package command
import (
"github.com/mitchellh/cli"
)
// Meta is for `*Command` struct.
type Meta struct {
UI *cli.BasicUi
CmdName string
SubCmdName string
Version string
}

View File

@@ -4,12 +4,15 @@ Command mailfull is a CLI application using the mailfull package.
package main
import (
"bytes"
"flag"
"fmt"
"os"
"path/filepath"
"runtime"
"github.com/directorz/mailfull-go"
"github.com/directorz/mailfull-go/cmd/mailfull/command"
"github.com/directorz/mailfull-go/cmd"
"github.com/mitchellh/cli"
)
@@ -20,8 +23,9 @@ var (
func init() {
if gittag != "" {
version = version + "-" + gittag
version += "-" + gittag
}
version += fmt.Sprintf(" (built with %s)", runtime.Version())
}
func main() {
@@ -31,7 +35,7 @@ func main() {
Args: os.Args[1:],
}
meta := command.Meta{
meta := cmd.Meta{
UI: &cli.BasicUi{
Reader: os.Stdin,
Writer: os.Stdout,
@@ -44,95 +48,95 @@ func main() {
c.Commands = map[string]cli.CommandFactory{
"init": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.InitCommand{Meta: meta}, nil
return &CmdInit{Meta: meta}, nil
},
"genconfig": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.GenConfigCommand{Meta: meta}, nil
return &CmdGenConfig{Meta: meta}, nil
},
"domains": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.DomainsCommand{Meta: meta}, nil
return &CmdDomains{Meta: meta}, nil
},
"domainadd": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.DomainAddCommand{Meta: meta}, nil
return &CmdDomainAdd{Meta: meta}, nil
},
"domaindel": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.DomainDelCommand{Meta: meta}, nil
return &CmdDomainDel{Meta: meta}, nil
},
"domaindisable": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.DomainDisableCommand{Meta: meta}, nil
return &CmdDomainDisable{Meta: meta}, nil
},
"domainenable": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.DomainEnableCommand{Meta: meta}, nil
return &CmdDomainEnable{Meta: meta}, nil
},
"aliasdomains": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.AliasDomainsCommand{Meta: meta}, nil
return &CmdAliasDomains{Meta: meta}, nil
},
"aliasdomainadd": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.AliasDomainAddCommand{Meta: meta}, nil
return &CmdAliasDomainAdd{Meta: meta}, nil
},
"aliasdomaindel": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.AliasDomainDelCommand{Meta: meta}, nil
return &CmdAliasDomainDel{Meta: meta}, nil
},
"users": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.UsersCommand{Meta: meta}, nil
return &CmdUsers{Meta: meta}, nil
},
"useradd": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.UserAddCommand{Meta: meta}, nil
return &CmdUserAdd{Meta: meta}, nil
},
"userdel": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.UserDelCommand{Meta: meta}, nil
return &CmdUserDel{Meta: meta}, nil
},
"userpasswd": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.UserPasswdCommand{Meta: meta}, nil
return &CmdUserPasswd{Meta: meta}, nil
},
"usercheckpw": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.UserCheckPwCommand{Meta: meta}, nil
return &CmdUserCheckPw{Meta: meta}, nil
},
"aliasusers": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.AliasUsersCommand{Meta: meta}, nil
return &CmdAliasUsers{Meta: meta}, nil
},
"aliasuseradd": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.AliasUserAddCommand{Meta: meta}, nil
return &CmdAliasUserAdd{Meta: meta}, nil
},
"aliasusermod": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.AliasUserModCommand{Meta: meta}, nil
return &CmdAliasUserMod{Meta: meta}, nil
},
"aliasuserdel": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.AliasUserDelCommand{Meta: meta}, nil
return &CmdAliasUserDel{Meta: meta}, nil
},
"catchall": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.CatchAllCommand{Meta: meta}, nil
return &CmdCatchAll{Meta: meta}, nil
},
"catchallset": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.CatchAllSetCommand{Meta: meta}, nil
return &CmdCatchAllSet{Meta: meta}, nil
},
"catchallunset": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.CatchAllUnsetCommand{Meta: meta}, nil
return &CmdCatchAllUnset{Meta: meta}, nil
},
"commit": func() (cli.Command, error) {
meta.SubCmdName = c.Subcommand()
return &command.CommitCommand{Meta: meta}, nil
return &CmdCommit{Meta: meta}, nil
},
}
@@ -143,3 +147,17 @@ func main() {
os.Exit(exitCode)
}
// 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
}

20
cmd/meta.go Normal file
View File

@@ -0,0 +1,20 @@
package cmd
import (
"fmt"
"github.com/mitchellh/cli"
)
// Meta contains options to execute a command.
type Meta struct {
UI *cli.BasicUi
CmdName string
SubCmdName string
Version string
}
// Errorf prints the error to ErrorWriter with the prefix string.
func (m Meta) Errorf(format string, v ...interface{}) {
fmt.Fprintf(m.UI.ErrorWriter, "[ERR] "+format, v...)
}

View File

@@ -9,33 +9,84 @@ import (
"strings"
)
// GenerateDatabases generates databases from the MailData directory.
func (r *Repository) GenerateDatabases(md *MailData) error {
sort.Sort(DomainSlice(md.Domains))
sort.Sort(AliasDomainSlice(md.AliasDomains))
// repoData represents a repoData.
type repoData struct {
Domains []*Domain
AliasDomains []*AliasDomain
}
for _, domain := range md.Domains {
sort.Sort(UserSlice(domain.Users))
sort.Sort(AliasUserSlice(domain.AliasUsers))
// repoData returns a repoData.
func (r *Repository) repoData() (*repoData, error) {
domains, err := r.Domains()
if err != nil {
return nil, err
}
aliasDomains, err := r.AliasDomains()
if err != nil {
return nil, err
}
for _, domain := range domains {
users, err := r.Users(domain.Name())
if err != nil {
return nil, err
}
domain.Users = users
aliasUsers, err := r.AliasUsers(domain.Name())
if err != nil {
return nil, err
}
domain.AliasUsers = aliasUsers
catchAllUser, err := r.CatchAllUser(domain.Name())
if err != nil {
return nil, err
}
domain.CatchAllUser = catchAllUser
}
rd := &repoData{
Domains: domains,
AliasDomains: aliasDomains,
}
return rd, nil
}
// GenerateDatabases generates databases from the Repository.
func (r *Repository) GenerateDatabases() error {
rd, err := r.repoData()
if err != nil {
return err
}
sort.Slice(rd.Domains, func(i, j int) bool { return rd.Domains[i].Name() < rd.Domains[j].Name() })
sort.Slice(rd.AliasDomains, func(i, j int) bool { return rd.AliasDomains[i].Name() < rd.AliasDomains[j].Name() })
for _, domain := range rd.Domains {
sort.Slice(domain.Users, func(i, j int) bool { return domain.Users[i].Name() < domain.Users[j].Name() })
sort.Slice(domain.AliasUsers, func(i, j int) bool { return domain.AliasUsers[i].Name() < domain.AliasUsers[j].Name() })
}
// Generate files
if err := r.generateDbDomains(md); err != nil {
if err := r.generateDbDomains(rd); err != nil {
return err
}
if err := r.generateDbDestinations(md); err != nil {
if err := r.generateDbDestinations(rd); err != nil {
return err
}
if err := r.generateDbMaildirs(md); err != nil {
if err := r.generateDbMaildirs(rd); err != nil {
return err
}
if err := r.generateDbLocaltable(md); err != nil {
if err := r.generateDbLocaltable(rd); err != nil {
return err
}
if err := r.generateDbForwards(md); err != nil {
if err := r.generateDbForwards(rd); err != nil {
return err
}
if err := r.generateDbPasswords(md); err != nil {
if err := r.generateDbPasswords(rd); err != nil {
return err
}
@@ -59,7 +110,7 @@ func (r *Repository) GenerateDatabases(md *MailData) error {
return nil
}
func (r *Repository) generateDbDomains(md *MailData) error {
func (r *Repository) generateDbDomains(rd *repoData) error {
dbDomains, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbDomains))
if err != nil {
return err
@@ -69,7 +120,7 @@ func (r *Repository) generateDbDomains(md *MailData) error {
}
defer dbDomains.Close()
for _, domain := range md.Domains {
for _, domain := range rd.Domains {
if domain.Disabled() {
continue
}
@@ -79,7 +130,7 @@ func (r *Repository) generateDbDomains(md *MailData) error {
}
}
for _, aliasDomain := range md.AliasDomains {
for _, aliasDomain := range rd.AliasDomains {
if _, err := fmt.Fprintf(dbDomains, "%s virtual\n", aliasDomain.Name()); err != nil {
return err
}
@@ -88,7 +139,7 @@ func (r *Repository) generateDbDomains(md *MailData) error {
return nil
}
func (r *Repository) generateDbDestinations(md *MailData) error {
func (r *Repository) generateDbDestinations(rd *repoData) error {
dbDestinations, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbDestinations))
if err != nil {
return err
@@ -98,7 +149,7 @@ func (r *Repository) generateDbDestinations(md *MailData) error {
}
defer dbDestinations.Close()
for _, domain := range md.Domains {
for _, domain := range rd.Domains {
if domain.Disabled() {
continue
}
@@ -123,7 +174,7 @@ func (r *Repository) generateDbDestinations(md *MailData) error {
}
}
for _, aliasDomain := range md.AliasDomains {
for _, aliasDomain := range rd.AliasDomains {
if aliasDomain.Target() == domain.Name() {
if _, err := fmt.Fprintf(dbDestinations, "%s@%s %s@%s\n", userName, aliasDomain.Name(), user.Name(), domain.Name()); err != nil {
return err
@@ -137,7 +188,7 @@ func (r *Repository) generateDbDestinations(md *MailData) error {
return err
}
for _, aliasDomain := range md.AliasDomains {
for _, aliasDomain := range rd.AliasDomains {
if aliasDomain.Target() == domain.Name() {
if _, err := fmt.Fprintf(dbDestinations, "%s@%s %s@%s\n", aliasUser.Name(), aliasDomain.Name(), aliasUser.Name(), domain.Name()); err != nil {
return err
@@ -150,7 +201,7 @@ func (r *Repository) generateDbDestinations(md *MailData) error {
return nil
}
func (r *Repository) generateDbMaildirs(md *MailData) error {
func (r *Repository) generateDbMaildirs(rd *repoData) error {
dbMaildirs, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbMaildirs))
if err != nil {
return err
@@ -160,7 +211,7 @@ func (r *Repository) generateDbMaildirs(md *MailData) error {
}
defer dbMaildirs.Close()
for _, domain := range md.Domains {
for _, domain := range rd.Domains {
if domain.Disabled() {
continue
}
@@ -175,7 +226,7 @@ func (r *Repository) generateDbMaildirs(md *MailData) error {
return nil
}
func (r *Repository) generateDbLocaltable(md *MailData) error {
func (r *Repository) generateDbLocaltable(rd *repoData) error {
dbLocaltable, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbLocaltable))
if err != nil {
return err
@@ -185,7 +236,7 @@ func (r *Repository) generateDbLocaltable(md *MailData) error {
}
defer dbLocaltable.Close()
for _, domain := range md.Domains {
for _, domain := range rd.Domains {
if domain.Disabled() {
continue
}
@@ -203,7 +254,7 @@ func (r *Repository) generateDbLocaltable(md *MailData) error {
return nil
}
func (r *Repository) generateDbForwards(md *MailData) error {
func (r *Repository) generateDbForwards(rd *repoData) error {
dbForwards, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbForwards))
if err != nil {
return err
@@ -213,7 +264,7 @@ func (r *Repository) generateDbForwards(md *MailData) error {
}
defer dbForwards.Close()
for _, domain := range md.Domains {
for _, domain := range rd.Domains {
if domain.Disabled() {
continue
}
@@ -243,7 +294,7 @@ func (r *Repository) generateDbForwards(md *MailData) error {
return nil
}
func (r *Repository) generateDbPasswords(md *MailData) error {
func (r *Repository) generateDbPasswords(rd *repoData) error {
dbPasswords, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbPasswords))
if err != nil {
return err
@@ -253,7 +304,7 @@ func (r *Repository) generateDbPasswords(md *MailData) error {
}
defer dbPasswords.Close()
for _, domain := range md.Domains {
for _, domain := range rd.Domains {
if domain.Disabled() {
continue
}

View File

@@ -3,3 +3,4 @@ Documentation
- [Configuration](configuration.md)
- [Migrating from mailfull](migrating_from_mailfull.md)
- [Commands Guide 日本語](commands_guide_ja.md)

200
doc/commands_guide_ja.md Normal file
View File

@@ -0,0 +1,200 @@
# Mailfull の使い方
* ユーザは `mailfull` にて実行してください。
* すべてのコマンドは、`-h` オプションで簡単な使用方法を出力して終了します。
* すべてのコマンドは、`-v` オプションでバージョンを出力して終了します。
* `-n` オプションでデータベースをアップデートしません。(直ちに変更を行いません)
## ドメイン
### ドメインの追加
$ mailfull2 domainadd example.com
`example.com` が追加され、`postmaster@example.com` が追加されます。
`postmaster@example.com` のパスワードは付与されませんので `userpasswd` コマンドで対応してください。
### ドメインの削除
$ mailfull2 domaindel example.com
`example.com` が削除されます。
ドメインディレクトリは同階層にドット付きでバックアップされます。
### ドメインのリストアップ
$ mailfull2 domains
設定されているドメインがリストアップされます。
## ユーザ
### ユーザの追加
$ mailfull2 useradd user@example.com
`user@example.com` が追加されます。
パスワードは付与されませんので `userpasswd` コマンドで対応してください。
SMTP-AUTH, POP/IMAP のユーザ名は、`user@example.com` となります。
### ユーザの削除
$ mailfull2 userdel user@example.com
`postmaster` は削除できません。
ユーザディレクトリは同階層にドット付きバックアップされます。
### パスワードの変更
$ mailfull2 userpasswd user@example.com
Enter new password for user@example.com:
Retype new password:
`user@example.com` のパスワードを設定、変更します。
### ユーザのリストアップ
$ mailfull2 users example.com
`example.com` のユーザがリストアップされます。
### パスワードのチェック
$ mailfull2 usercheckpw user@example.com
Enter password for user@example.com:
The password you entered is correct.
$ echo $?
0
$ mailfull2 usercheckpw user@example.com
Enter password for user@example.com:
The password you entered is incorrect.
$ echo $?
1
パスワードは引数で与えることもできます。
パスワードの正誤に応じたメッセージが表示されます。
コマンドの戻り値として、正しい場合 0、違う場合 1 が戻ります。
## エイリアス
### エイリアスの新設
$ maulfull2 aliasuseradd aliasname@example.com dest@example.org[,...]
`aliasname@example.com` 宛のメールを `dest@example.org` へ転送するエイリアスを作成します。
### エイリアスの編集
$ maulfull2 aliasusermod aliasname@example.com dest2@example.org[,...]
`aliasname@example.com` 宛のメールを `dest2@example.org` へ転送するエイリアスへ書き換えます。
### エイリアスの解除
$ mailfull2 aliasuserdel aliasname@example.com
`aliasname@example.com` のエイリアス設定を削除します。
### エイリアスのリストアップ
$ mailfull2 aliasusers example.com
ドメインに設定されているエイリアスのリストが出力されます。
## メーリングリスト
### メーリングリストの一覧
$ mailfull2 mailinglists example.com
`example.com` のMLがリストアップされます。
### メーリングリストの新規作成
$ mailfull2 mailinglistadd example.com ml user@example.com
`ml@example.com` というメーリングリストを作成し、メンバーに `user@example.com` を含めます。
### 既存のメーリングリストに配信先を追加
$ mailfull2 mailinglistuseradd example.com ml user2@example.com
`ml@example.com` というメーリングリストに、メンバーに `user2@example.com` を追加します。
### 既存のメーリングリストの配信先を確認
$ mailfull2 mailinglistusers example.com ml
`ml@example.com` というメーリングリストのメンバーを確認します。
### 既存のメーリングリストから配信先を削除
$ mailfull2 mailinglistuserdel example.com ml user@example.com
`ml@example.com` というメーリングリストから、メンバー `user@example.com` を削除します。
### メーリングリストの削除
$ mailfull2 mailinglistdel example.com ml
`ml@example.com` というメーリングリストを削除します。
## キャッチオール
### キャッチオールの設定
$ mailfull2 catchallset example.com user
`example.com` の全てのユーザ宛のメールを、
ユーザが存在しなければ、`user@example.com` が受け取るようになります。
### キャッチオールの解除
$ mailfull2 catchalldel example.com
`example.com` に設定されているキャッチオールを解除します。
### キャッチオールの取得
$ mailfull2 catchall example.com
`example.com` にキャッチオールが設定されていれば、出力します。
## エイリアスドメイン
### エイリアスドメインの追加
$ mailfull2 aliasdomainadd alias.example.com example.com
`example.com` 宛のメールが、`alias.example.com` でも
受け取れるようになります。
### エイリアスドメインの解除
$ mailfull2 aliasdomaindel alias.example.com
エイリアスドメインを解除します。
### エイリアスドメインのリストアップ
$ mailfull2 aliasdomains example.com
`example.com` に設定されているエイリアスドメインをリストアップします。
## その他
### commit
$ ./commit
`/home/mailfull/domains` 以下から設定を生成し、
`/home/mailfull/etc` 以下の設定ファイルにまとめ、各種データベースを作成します。

View File

@@ -3,10 +3,10 @@ Configuration
`.mailfull/config`
| key | type | default | required | description |
|:----|:-----|:--------|:---------|:------------|
| dir_database | string | `"./etc"` | no | A relative path from repository dir (or a absolute path) |
| dir_maildata | string | `"./domains"` | no | A relative path from repository dir (or a absolute path) |
| username | string | The username who executed `mailfull init` | **yes** | It used for setting owner of database files and maildata files. |
| cmd_postalias | string | `"postalias"` | no | Command name or path |
| cmd_postmap | string | `"postmap"` | no | Command name or path |
| key | type | default | required | description |
|:--------------|:-------|:------------------------------------------|:---------|:----------------------------------------------------------------|
| dir_database | string | `"./etc"` | no | A relative path from repository dir (or a absolute path) |
| dir_maildata | string | `"./domains"` | no | A relative path from repository dir (or a absolute path) |
| username | string | The username who executed `mailfull init` | **yes** | It used for setting owner of database files and maildata files. |
| cmd_postalias | string | `"postalias"` | no | Command name or path |
| cmd_postmap | string | `"postmap"` | no | Command name or path |

View File

@@ -17,13 +17,6 @@ type Domain struct {
CatchAllUser *CatchAllUser
}
// DomainSlice attaches the methods of sort.Interface to []*Domain.
type DomainSlice []*Domain
func (p DomainSlice) Len() int { return len(p) }
func (p DomainSlice) Less(i, j int) bool { return p[i].Name() < p[j].Name() }
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) {
d := &Domain{}

View File

@@ -1,47 +0,0 @@
package mailfull
// MailData represents a MailData.
type MailData struct {
Domains []*Domain
AliasDomains []*AliasDomain
}
// MailData returns a MailData.
func (r *Repository) MailData() (*MailData, error) {
domains, err := r.Domains()
if err != nil {
return nil, err
}
aliasDomains, err := r.AliasDomains()
if err != nil {
return nil, err
}
for _, domain := range domains {
users, err := r.Users(domain.Name())
if err != nil {
return nil, err
}
domain.Users = users
aliasUsers, err := r.AliasUsers(domain.Name())
if err != nil {
return nil, err
}
domain.AliasUsers = aliasUsers
catchAllUser, err := r.CatchAllUser(domain.Name())
if err != nil {
return nil, err
}
domain.CatchAllUser = catchAllUser
}
mailData := &MailData{
Domains: domains,
AliasDomains: aliasDomains,
}
return mailData, nil
}

10
user.go
View File

@@ -19,13 +19,6 @@ type User struct {
forwards []string
}
// UserSlice attaches the methods of sort.Interface to []*User.
type UserSlice []*User
func (p UserSlice) Len() int { return len(p) }
func (p UserSlice) Less(i, j int) bool { return p[i].Name() < p[j].Name() }
func (p UserSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// NewUser creates a new User instance.
func NewUser(name, hashedPassword string, forwards []string) (*User, error) {
u := &User{}
@@ -107,6 +100,9 @@ func (r *Repository) Users(domainName string) ([]*User, error) {
forwards, err := r.userForwards(domainName, name)
if err != nil {
if err == ErrInvalidUserName {
continue
}
return nil, err
}

View File

@@ -33,20 +33,20 @@ func validAliasDomainTarget(target string) bool {
// validUserName returns true if the input is correct format.
func validUserName(name string) bool {
return regexp.MustCompile(`^[^\s@]+$`).MatchString(name)
return regexp.MustCompile(`^[^\.\s@][^\s@]+$`).MatchString(name)
}
// validAliasUserName returns true if the input is correct format.
func validAliasUserName(name string) bool {
return regexp.MustCompile(`^[^\s@]+$`).MatchString(name)
return regexp.MustCompile(`^[^\.\s@][^\s@]+$`).MatchString(name)
}
// validAliasUserTarget returns true if the input is correct format.
func validAliasUserTarget(target string) bool {
return regexp.MustCompile(`^[^\s@]+@([A-Za-z0-9\-]+\.)*[A-Za-z]+$`).MatchString(target)
return regexp.MustCompile(`^[^\.\s@][^\s@]+@([A-Za-z0-9\-]+\.)*[A-Za-z]+$`).MatchString(target)
}
// validCatchAllUserName returns true if the input is correct format.
func validCatchAllUserName(name string) bool {
return regexp.MustCompile(`^[^\s@]+$`).MatchString(name)
return regexp.MustCompile(`^[^\.\s@][^\s@]+$`).MatchString(name)
}

View File

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