mirror of
https://github.com/directorz/mailfull-go.git
synced 2025-12-20 19:17:02 +00:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1ecad7df3 | ||
|
|
0f0a3835fc | ||
|
|
a145712856 | ||
|
|
ad18a41b64 | ||
|
|
ac6a8526b1 | ||
|
|
067c8f6903 | ||
|
|
e7254c6df6 | ||
|
|
8ecd1f0f79 | ||
|
|
de6ddf7e1b | ||
|
|
58b508b7fa | ||
|
|
78ba1d2674 | ||
|
|
b4461b66ca | ||
|
|
afb8e4eaf4 | ||
|
|
e32523d0b2 | ||
|
|
188be4c3e8 | ||
|
|
de4bddc161 | ||
|
|
f618eb24e6 | ||
|
|
096193d93d | ||
|
|
e32ed61771 | ||
|
|
3ae4d8d590 | ||
|
|
d4343eacce | ||
|
|
a97a9e343b | ||
|
|
f61d18f31f | ||
|
|
9c92ac9656 | ||
|
|
30f0279751 | ||
|
|
c7e56f26af | ||
|
|
58b50cb3f6 | ||
|
|
146ab299d0 | ||
|
|
2e87209ad2 | ||
|
|
5a178c350b | ||
|
|
b884655a7c | ||
|
|
552ed95a0f | ||
|
|
2bb46731d0 | ||
|
|
5a64a543ca | ||
|
|
d0dd68e2b6 | ||
|
|
1daea44e49 | ||
|
|
3ac5856917 | ||
|
|
3cf4815565 | ||
|
|
52e5d32c01 | ||
|
|
b1d13b49f5 | ||
|
|
46cf349015 | ||
|
|
9be507565d | ||
|
|
58b4e49fe8 | ||
|
|
cb6e9ce2c5 | ||
|
|
db554a1da1 | ||
|
|
708e132ccc | ||
|
|
3a1d4a588c | ||
|
|
50d429ad78 | ||
|
|
0118652074 | ||
|
|
bf4b63556a | ||
|
|
24ee3c26b0 | ||
|
|
49dd05f3bf | ||
|
|
009ee84e63 | ||
|
|
281d5a4a9d | ||
|
|
c2dca41057 | ||
|
|
4f99f11732 | ||
|
|
a3d3684fda | ||
|
|
c183bba7aa | ||
|
|
b52a7cde7f | ||
|
|
0926ffd318 | ||
|
|
c9201c8fc1 | ||
|
|
fe16bb86f9 | ||
|
|
bd6228197a | ||
|
|
1329747f54 | ||
|
|
ab3c3315f9 | ||
|
|
a76596c348 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1 +1,6 @@
|
|||||||
/cli/mailfull/mailfull
|
/vendor
|
||||||
|
/build
|
||||||
|
/release
|
||||||
|
/github_token
|
||||||
|
|
||||||
|
/cmd/mailfull/mailfull
|
||||||
|
|||||||
74
Gopkg.lock
generated
Normal file
74
Gopkg.lock
generated
Normal 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
0
Gopkg.toml
Normal file
78
Makefile
Normal file
78
Makefile
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
GOVERSION=$(shell go version)
|
||||||
|
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)))
|
||||||
|
GITTAG=$(shell git rev-parse --short HEAD)
|
||||||
|
|
||||||
|
default: build
|
||||||
|
|
||||||
|
FORCE:
|
||||||
|
.PHONY: FORCE
|
||||||
|
|
||||||
|
$(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:
|
||||||
|
@$(MAKE) .build-docker GOOS=linux GOARCH=amd64
|
||||||
|
|
||||||
|
build-linux-386:
|
||||||
|
@$(MAKE) .build-docker GOOS=linux GOARCH=386
|
||||||
|
|
||||||
|
|
||||||
|
release: release-linux-amd64 release-linux-386
|
||||||
|
|
||||||
|
release-linux-amd64: build-linux-amd64
|
||||||
|
@$(MAKE) release-doc release-targz GOOS=linux GOARCH=amd64
|
||||||
|
|
||||||
|
release-linux-386: build-linux-386
|
||||||
|
@$(MAKE) release-doc release-targz GOOS=linux GOARCH=386
|
||||||
|
|
||||||
|
release-doc:
|
||||||
|
cp -a README.md doc $(DIR_BUILD)/mailfull_$(GOOS)_$(GOARCH)
|
||||||
|
|
||||||
|
release-targz: dir-$(DIR_RELEASE)
|
||||||
|
tar zcfp $(DIR_RELEASE)/mailfull_$(GOOS)_$(GOARCH).tar.gz -C $(DIR_BUILD) mailfull_$(GOOS)_$(GOARCH)
|
||||||
|
|
||||||
|
dir-$(DIR_RELEASE):
|
||||||
|
mkdir -p $(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)
|
||||||
11
README.md
11
README.md
@@ -16,6 +16,11 @@ Features
|
|||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
### Binary
|
||||||
|
|
||||||
|
You can download archive file from [releases page](https://github.com/directorz/mailfull-go/releases) .
|
||||||
|
Download and unpack the archive file, and put the binary file to somewhere you want.
|
||||||
|
|
||||||
### go get
|
### go get
|
||||||
|
|
||||||
Installed in `$GOPATH/bin`
|
Installed in `$GOPATH/bin`
|
||||||
@@ -39,6 +44,7 @@ Initialize a directory as a Mailfull repository.
|
|||||||
```
|
```
|
||||||
$ mkdir /path/to/repo && cd /path/to/repo
|
$ mkdir /path/to/repo && cd /path/to/repo
|
||||||
$ mailfull init
|
$ mailfull init
|
||||||
|
$ mailfull commit
|
||||||
```
|
```
|
||||||
|
|
||||||
Generate configurations for Postfix and Dovecot. (Edit as needed.)
|
Generate configurations for Postfix and Dovecot. (Edit as needed.)
|
||||||
@@ -66,3 +72,8 @@ Add a new domain and user.
|
|||||||
```
|
```
|
||||||
|
|
||||||
Enjoy!
|
Enjoy!
|
||||||
|
|
||||||
|
More info
|
||||||
|
---------
|
||||||
|
|
||||||
|
See [documentation](doc/README.md)
|
||||||
|
|||||||
@@ -15,13 +15,6 @@ type AliasDomain struct {
|
|||||||
target string
|
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.
|
// NewAliasDomain creates a new AliasDomain instance.
|
||||||
func NewAliasDomain(name, target string) (*AliasDomain, error) {
|
func NewAliasDomain(name, target string) (*AliasDomain, error) {
|
||||||
ad := &AliasDomain{}
|
ad := &AliasDomain{}
|
||||||
@@ -190,7 +183,7 @@ func (r *Repository) writeAliasDomainsFile(aliasDomains []*AliasDomain) error {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
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 {
|
for _, aliasDomain := range aliasDomains {
|
||||||
if _, err := fmt.Fprintf(file, "%s:%s\n", aliasDomain.Name(), aliasDomain.Target()); err != nil {
|
if _, err := fmt.Fprintf(file, "%s:%s\n", aliasDomain.Name(), aliasDomain.Target()); err != nil {
|
||||||
|
|||||||
@@ -21,13 +21,6 @@ type AliasUser struct {
|
|||||||
targets []string
|
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.
|
// NewAliasUser creates a new AliasUser instance.
|
||||||
func NewAliasUser(name string, targets []string) (*AliasUser, error) {
|
func NewAliasUser(name string, targets []string) (*AliasUser, error) {
|
||||||
au := &AliasUser{}
|
au := &AliasUser{}
|
||||||
@@ -233,7 +226,7 @@ func (r *Repository) writeAliasUsersFile(domainName string, aliasUsers []*AliasU
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
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 {
|
for _, aliasUser := range aliasUsers {
|
||||||
if _, err := fmt.Fprintf(file, "%s:%s\n", aliasUser.Name(), strings.Join(aliasUser.Targets(), ",")); err != nil {
|
if _, err := fmt.Fprintf(file, "%s:%s\n", aliasUser.Name(), strings.Join(aliasUser.Targets(), ",")); err != nil {
|
||||||
|
|||||||
@@ -1,26 +1,27 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
mailfull "github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AliasDomainAddCommand represents a AliasDomainAddCommand.
|
// CmdAliasDomainAdd represents a CmdAliasDomainAdd.
|
||||||
type AliasDomainAddCommand struct {
|
type CmdAliasDomainAdd struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *AliasDomainAddCommand) Synopsis() string {
|
func (c *CmdAliasDomainAdd) Synopsis() string {
|
||||||
return "Create a new aliasdomain."
|
return "Create a new aliasdomain."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *AliasDomainAddCommand) Help() string {
|
func (c *CmdAliasDomainAdd) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s domain target
|
%s %s [-n] domain target
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -30,6 +31,10 @@ Required Args:
|
|||||||
The domain name that you want to create.
|
The domain name that you want to create.
|
||||||
target
|
target
|
||||||
The target domain name.
|
The target domain name.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -38,7 +43,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *AliasDomainAddCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) != 2 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -49,30 +60,26 @@ func (c *AliasDomainAddCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
aliasDomain, err := mailfull.NewAliasDomain(aliasDomainName, targetDomainName)
|
aliasDomain, err := mailfull.NewAliasDomain(aliasDomainName, targetDomainName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.AliasDomainCreate(aliasDomain); err != nil {
|
if err := repo.AliasDomainCreate(aliasDomain); err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
mailfull "github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AliasDomainDelCommand represents a AliasDomainDelCommand.
|
// CmdAliasDomainDel represents a CmdAliasDomainDel.
|
||||||
type AliasDomainDelCommand struct {
|
type CmdAliasDomainDel struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *AliasDomainDelCommand) Synopsis() string {
|
func (c *CmdAliasDomainDel) Synopsis() string {
|
||||||
return "Delete a aliasdomain."
|
return "Delete a aliasdomain."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *AliasDomainDelCommand) Help() string {
|
func (c *CmdAliasDomainDel) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s domain
|
%s %s [-n] domain
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -28,6 +29,10 @@ Description:
|
|||||||
Required Args:
|
Required Args:
|
||||||
domain
|
domain
|
||||||
The domain name that you want to delete.
|
The domain name that you want to delete.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -36,7 +41,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *AliasDomainDelCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -46,24 +57,20 @@ func (c *AliasDomainDelCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.AliasDomainRemove(aliasDomainName); err != nil {
|
if err := repo.AliasDomainRemove(aliasDomainName); err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,24 +1,25 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
mailfull "github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AliasDomainsCommand represents a AliasDomainsCommand.
|
// CmdAliasDomains represents a CmdAliasDomains.
|
||||||
type AliasDomainsCommand struct {
|
type CmdAliasDomains struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *AliasDomainsCommand) Synopsis() string {
|
func (c *CmdAliasDomains) Synopsis() string {
|
||||||
return "Show aliasdomains."
|
return "Show aliasdomains."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *AliasDomainsCommand) Help() string {
|
func (c *CmdAliasDomains) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s [domain]
|
%s %s [domain]
|
||||||
@@ -37,7 +38,7 @@ Optional Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// 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 {
|
if len(args) > 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -50,16 +51,16 @@ func (c *AliasDomainsCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
aliasDomains, err := repo.AliasDomains()
|
aliasDomains, err := repo.AliasDomains()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
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 {
|
for _, aliasDomain := range aliasDomains {
|
||||||
if targetDomainName != "" {
|
if targetDomainName != "" {
|
||||||
@@ -1,27 +1,28 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
mailfull "github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AliasUserAddCommand represents a AliasUserAddCommand.
|
// CmdAliasUserAdd represents a CmdAliasUserAdd.
|
||||||
type AliasUserAddCommand struct {
|
type CmdAliasUserAdd struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *AliasUserAddCommand) Synopsis() string {
|
func (c *CmdAliasUserAdd) Synopsis() string {
|
||||||
return "Create a new aliasuser."
|
return "Create a new aliasuser."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *AliasUserAddCommand) Help() string {
|
func (c *CmdAliasUserAdd) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s address target [target...]
|
%s %s [-n] address target [target...]
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -31,6 +32,10 @@ Required Args:
|
|||||||
The email address that you want to create.
|
The email address that you want to create.
|
||||||
target
|
target
|
||||||
Target email addresses.
|
Target email addresses.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -39,7 +44,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *AliasUserAddCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) < 2 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -58,30 +69,26 @@ func (c *AliasUserAddCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
aliasUser, err := mailfull.NewAliasUser(aliasUserName, targets)
|
aliasUser, err := mailfull.NewAliasUser(aliasUserName, targets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.AliasUserCreate(domainName, aliasUser); err != nil {
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,27 +1,28 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
mailfull "github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AliasUserDelCommand represents a AliasUserDelCommand.
|
// CmdAliasUserDel represents a CmdAliasUserDel.
|
||||||
type AliasUserDelCommand struct {
|
type CmdAliasUserDel struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *AliasUserDelCommand) Synopsis() string {
|
func (c *CmdAliasUserDel) Synopsis() string {
|
||||||
return "Delete a aliasuser."
|
return "Delete a aliasuser."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *AliasUserDelCommand) Help() string {
|
func (c *CmdAliasUserDel) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s address
|
%s %s [-n] address
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -29,6 +30,10 @@ Description:
|
|||||||
Required Args:
|
Required Args:
|
||||||
address
|
address
|
||||||
The email address that you want to delete.
|
The email address that you want to delete.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -37,7 +42,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *AliasUserDelCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -54,24 +65,20 @@ func (c *AliasUserDelCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.AliasUserRemove(domainName, aliasUserName); err != nil {
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,27 +1,28 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
mailfull "github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AliasUserModCommand represents a AliasUserModCommand.
|
// CmdAliasUserMod represents a CmdAliasUserMod.
|
||||||
type AliasUserModCommand struct {
|
type CmdAliasUserMod struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *AliasUserModCommand) Synopsis() string {
|
func (c *CmdAliasUserMod) Synopsis() string {
|
||||||
return "Modify a aliasuser."
|
return "Modify a aliasuser."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *AliasUserModCommand) Help() string {
|
func (c *CmdAliasUserMod) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s address target [target...]
|
%s %s [-n] address target [target...]
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -31,6 +32,10 @@ Required Args:
|
|||||||
The email address that you want to modify.
|
The email address that you want to modify.
|
||||||
target
|
target
|
||||||
Target email addresses.
|
Target email addresses.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -39,7 +44,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *AliasUserModCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) < 2 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -58,39 +69,35 @@ func (c *AliasUserModCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
aliasUser, err := repo.AliasUser(domainName, aliasUserName)
|
aliasUser, err := repo.AliasUser(domainName, aliasUserName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
if aliasUser == nil {
|
if aliasUser == nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", mailfull.ErrAliasUserNotExist)
|
c.Meta.Errorf("%v\n", mailfull.ErrAliasUserNotExist)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := aliasUser.SetTargets(targets); err != nil {
|
if err := aliasUser.SetTargets(targets); err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.AliasUserUpdate(domainName, aliasUser); err != nil {
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,24 +1,25 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AliasUsersCommand represents a AliasUsersCommand.
|
// CmdAliasUsers represents a CmdAliasUsers.
|
||||||
type AliasUsersCommand struct {
|
type CmdAliasUsers struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *AliasUsersCommand) Synopsis() string {
|
func (c *CmdAliasUsers) Synopsis() string {
|
||||||
return "Show aliasusers."
|
return "Show aliasusers."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *AliasUsersCommand) Help() string {
|
func (c *CmdAliasUsers) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s domain
|
%s %s domain
|
||||||
@@ -37,7 +38,7 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// 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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -47,16 +48,16 @@ func (c *AliasUsersCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
aliasUsers, err := repo.AliasUsers(targetDomainName)
|
aliasUsers, err := repo.AliasUsers(targetDomainName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
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 {
|
for _, aliasUser := range aliasUsers {
|
||||||
fmt.Fprintf(c.UI.Writer, "%s\n", aliasUser.Name())
|
fmt.Fprintf(c.UI.Writer, "%s\n", aliasUser.Name())
|
||||||
@@ -1,23 +1,24 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CatchAllCommand represents a CatchAllCommand.
|
// CmdCatchAll represents a CmdCatchAll.
|
||||||
type CatchAllCommand struct {
|
type CmdCatchAll struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *CatchAllCommand) Synopsis() string {
|
func (c *CmdCatchAll) Synopsis() string {
|
||||||
return "Show a catchall user."
|
return "Show a catchall user."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *CatchAllCommand) Help() string {
|
func (c *CmdCatchAll) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s domain
|
%s %s domain
|
||||||
@@ -36,7 +37,7 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// 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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -46,13 +47,13 @@ func (c *CatchAllCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
catchAllUser, err := repo.CatchAllUser(domainName)
|
catchAllUser, err := repo.CatchAllUser(domainName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CatchAllSetCommand represents a CatchAllSetCommand.
|
// CmdCatchAllSet represents a CmdCatchAllSet.
|
||||||
type CatchAllSetCommand struct {
|
type CmdCatchAllSet struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *CatchAllSetCommand) Synopsis() string {
|
func (c *CmdCatchAllSet) Synopsis() string {
|
||||||
return "Set a catchall user."
|
return "Set a catchall user."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *CatchAllSetCommand) Help() string {
|
func (c *CmdCatchAllSet) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s domain user
|
%s %s [-n] domain user
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -30,6 +31,10 @@ Required Args:
|
|||||||
The domain name.
|
The domain name.
|
||||||
user
|
user
|
||||||
The user name that you want to set as catchall user.
|
The user name that you want to set as catchall user.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -38,7 +43,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *CatchAllSetCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) != 2 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -49,30 +60,26 @@ func (c *CatchAllSetCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
catchAllUser, err := mailfull.NewCatchAllUser(userName)
|
catchAllUser, err := mailfull.NewCatchAllUser(userName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.CatchAllUserSet(domainName, catchAllUser); err != nil {
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CatchAllUnsetCommand represents a CatchAllUnsetCommand.
|
// CmdCatchAllUnset represents a CmdCatchAllUnset.
|
||||||
type CatchAllUnsetCommand struct {
|
type CmdCatchAllUnset struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *CatchAllUnsetCommand) Synopsis() string {
|
func (c *CmdCatchAllUnset) Synopsis() string {
|
||||||
return "Unset a catchall user."
|
return "Unset a catchall user."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *CatchAllUnsetCommand) Help() string {
|
func (c *CmdCatchAllUnset) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s domain
|
%s %s [-n] domain
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -28,6 +29,10 @@ Description:
|
|||||||
Required Args:
|
Required Args:
|
||||||
domain
|
domain
|
||||||
The domain name.
|
The domain name.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -36,7 +41,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *CatchAllUnsetCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -46,24 +57,20 @@ func (c *CatchAllUnsetCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.CatchAllUserUnset(domainName); err != nil {
|
if err := repo.CatchAllUserUnset(domainName); err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
49
cmd/mailfull/cmd_commit.go
Normal file
49
cmd/mailfull/cmd_commit.go
Normal 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
|
||||||
|
}
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DomainAddCommand represents a DomainAddCommand.
|
// CmdDomainAdd represents a CmdDomainAdd.
|
||||||
type DomainAddCommand struct {
|
type CmdDomainAdd struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *DomainAddCommand) Synopsis() string {
|
func (c *CmdDomainAdd) Synopsis() string {
|
||||||
return "Create a new domain and postmaster."
|
return "Create a new domain and postmaster."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *DomainAddCommand) Help() string {
|
func (c *CmdDomainAdd) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s domain
|
%s %s [-n] domain
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -28,6 +29,10 @@ Description:
|
|||||||
Required Args:
|
Required Args:
|
||||||
domain
|
domain
|
||||||
The domain name that you want to create.
|
The domain name that you want to create.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -36,7 +41,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *DomainAddCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -46,41 +57,37 @@ func (c *DomainAddCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
domain, err := mailfull.NewDomain(domainName)
|
domain, err := mailfull.NewDomain(domainName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.DomainCreate(domain); err != nil {
|
if err := repo.DomainCreate(domain); err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := mailfull.NewUser("postmaster", mailfull.NeverMatchHashedPassword, nil)
|
user, err := mailfull.NewUser("postmaster", mailfull.NeverMatchHashedPassword, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.UserCreate(domainName, user); err != nil {
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DomainDelCommand represents a DomainDelCommand.
|
// CmdDomainDel represents a CmdDomainDel.
|
||||||
type DomainDelCommand struct {
|
type CmdDomainDel struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *DomainDelCommand) Synopsis() string {
|
func (c *CmdDomainDel) Synopsis() string {
|
||||||
return "Delete and backup a domain."
|
return "Delete and backup a domain."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *DomainDelCommand) Help() string {
|
func (c *CmdDomainDel) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s domain
|
%s %s [-n] domain
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -28,6 +29,10 @@ Description:
|
|||||||
Required Args:
|
Required Args:
|
||||||
domain
|
domain
|
||||||
The domain name that you want to delete.
|
The domain name that you want to delete.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -36,7 +41,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *DomainDelCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -46,24 +57,20 @@ func (c *DomainDelCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.DomainRemove(domainName); err != nil {
|
if err := repo.DomainRemove(domainName); err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
90
cmd/mailfull/cmd_domaindisable.go
Normal file
90
cmd/mailfull/cmd_domaindisable.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CmdDomainDisable represents a CmdDomainDisable.
|
||||||
|
type CmdDomainDisable struct {
|
||||||
|
cmd.Meta
|
||||||
|
}
|
||||||
|
|
||||||
|
// Synopsis returns a one-line synopsis.
|
||||||
|
func (c *CmdDomainDisable) Synopsis() string {
|
||||||
|
return "Disable a domain temporarily."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Help returns long-form help text.
|
||||||
|
func (c *CmdDomainDisable) 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 *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
|
||||||
|
}
|
||||||
|
|
||||||
|
domainName := args[0]
|
||||||
|
|
||||||
|
repo, err := mailfull.OpenRepository(".")
|
||||||
|
if err != nil {
|
||||||
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
domain, err := repo.Domain(domainName)
|
||||||
|
if err != nil {
|
||||||
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if domain == nil {
|
||||||
|
c.Meta.Errorf("%v\n", mailfull.ErrDomainNotExist)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
domain.SetDisabled(true)
|
||||||
|
|
||||||
|
if err := repo.DomainUpdate(domain); err != nil {
|
||||||
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if noCommit {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
90
cmd/mailfull/cmd_domainenable.go
Normal file
90
cmd/mailfull/cmd_domainenable.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CmdDomainEnable represents a CmdDomainEnable.
|
||||||
|
type CmdDomainEnable struct {
|
||||||
|
cmd.Meta
|
||||||
|
}
|
||||||
|
|
||||||
|
// Synopsis returns a one-line synopsis.
|
||||||
|
func (c *CmdDomainEnable) Synopsis() string {
|
||||||
|
return "Enable a domain."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Help returns long-form help text.
|
||||||
|
func (c *CmdDomainEnable) 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 *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
|
||||||
|
}
|
||||||
|
|
||||||
|
domainName := args[0]
|
||||||
|
|
||||||
|
repo, err := mailfull.OpenRepository(".")
|
||||||
|
if err != nil {
|
||||||
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
domain, err := repo.Domain(domainName)
|
||||||
|
if err != nil {
|
||||||
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if domain == nil {
|
||||||
|
c.Meta.Errorf("%v\n", mailfull.ErrDomainNotExist)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
domain.SetDisabled(false)
|
||||||
|
|
||||||
|
if err := repo.DomainUpdate(domain); err != nil {
|
||||||
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if noCommit {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
62
cmd/mailfull/cmd_domains.go
Normal file
62
cmd/mailfull/cmd_domains.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CmdDomains represents a CmdDomains.
|
||||||
|
type CmdDomains struct {
|
||||||
|
cmd.Meta
|
||||||
|
}
|
||||||
|
|
||||||
|
// Synopsis returns a one-line synopsis.
|
||||||
|
func (c *CmdDomains) Synopsis() string {
|
||||||
|
return "Show domains."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Help returns long-form help text.
|
||||||
|
func (c *CmdDomains) Help() string {
|
||||||
|
txt := fmt.Sprintf(`
|
||||||
|
Usage:
|
||||||
|
%s %s
|
||||||
|
|
||||||
|
Description:
|
||||||
|
%s
|
||||||
|
Disabled domains are marked "!" the beginning.
|
||||||
|
`,
|
||||||
|
c.CmdName, c.SubCmdName,
|
||||||
|
c.Synopsis())
|
||||||
|
|
||||||
|
return txt[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run runs the command and returns the exit status.
|
||||||
|
func (c *CmdDomains) Run(args []string) int {
|
||||||
|
repo, err := mailfull.OpenRepository(".")
|
||||||
|
if err != nil {
|
||||||
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
domains, err := repo.Domains()
|
||||||
|
if err != nil {
|
||||||
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
sort.Slice(domains, func(i, j int) bool { return domains[i].Name() < domains[j].Name() })
|
||||||
|
|
||||||
|
for _, domain := range domains {
|
||||||
|
disableStr := ""
|
||||||
|
if domain.Disabled() {
|
||||||
|
disableStr = "!"
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(c.UI.Writer, "%s%s\n", disableStr, domain.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -1,23 +1,24 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenConfigCommand represents a GenConfigCommand.
|
// CmdGenConfig represents a CmdGenConfig.
|
||||||
type GenConfigCommand struct {
|
type CmdGenConfig struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// 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."
|
return "Write a Postfix or Dovecot configuration to stdout."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *GenConfigCommand) Help() string {
|
func (c *CmdGenConfig) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s name
|
%s %s name
|
||||||
@@ -37,7 +38,7 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// 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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -47,7 +48,7 @@ func (c *GenConfigCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +60,7 @@ func (c *GenConfigCommand) Run(args []string) int {
|
|||||||
fmt.Fprintf(c.UI.Writer, "%s", repo.GenerateConfigDovecot())
|
fmt.Fprintf(c.UI.Writer, "%s", repo.GenerateConfigDovecot())
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] Specify \"postfix\" or \"dovecot\".\n")
|
c.Meta.Errorf("Specify \"postfix\" or \"dovecot\".\n")
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,23 +1,24 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitCommand represents a InitCommand.
|
// CmdInit represents a CmdInit.
|
||||||
type InitCommand struct {
|
type CmdInit struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *InitCommand) Synopsis() string {
|
func (c *CmdInit) Synopsis() string {
|
||||||
return "Initializes current directory as a Mailfull repository."
|
return "Initializes current directory as a Mailfull repository."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *InitCommand) Help() string {
|
func (c *CmdInit) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s
|
%s %s
|
||||||
@@ -32,9 +33,9 @@ Description:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// 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 {
|
if err := mailfull.InitRepository("."); err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,27 +1,28 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserAddCommand represents a UserAddCommand.
|
// CmdUserAdd represents a CmdUserAdd.
|
||||||
type UserAddCommand struct {
|
type CmdUserAdd struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *UserAddCommand) Synopsis() string {
|
func (c *CmdUserAdd) Synopsis() string {
|
||||||
return "Create a new user."
|
return "Create a new user."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *UserAddCommand) Help() string {
|
func (c *CmdUserAdd) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s address
|
%s %s [-n] address
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -29,6 +30,10 @@ Description:
|
|||||||
Required Args:
|
Required Args:
|
||||||
address
|
address
|
||||||
The email address that you want to create.
|
The email address that you want to create.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -37,7 +42,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *UserAddCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -55,30 +66,26 @@ func (c *UserAddCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := mailfull.NewUser(userName, mailfull.NeverMatchHashedPassword, nil)
|
user, err := mailfull.NewUser(userName, mailfull.NeverMatchHashedPassword, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.UserCreate(domainName, user); err != nil {
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,25 +1,26 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
"github.com/jsimonetti/pwscheme/ssha"
|
"github.com/jsimonetti/pwscheme/ssha"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserCheckPwCommand represents a UserCheckPwCommand.
|
// CmdUserCheckPw represents a CmdUserCheckPw.
|
||||||
type UserCheckPwCommand struct {
|
type CmdUserCheckPw struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *UserCheckPwCommand) Synopsis() string {
|
func (c *CmdUserCheckPw) Synopsis() string {
|
||||||
return "Check user's password."
|
return "Check user's password."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *UserCheckPwCommand) Help() string {
|
func (c *CmdUserCheckPw) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s address [password]
|
%s %s address [password]
|
||||||
@@ -34,7 +35,7 @@ Required Args:
|
|||||||
Optional Args:
|
Optional Args:
|
||||||
password
|
password
|
||||||
Specify the password instead of your typing.
|
Specify the password instead of your typing.
|
||||||
This option is not recommended because the password will be visible in your shell history.
|
This option is NOT recommended because the password will be visible in your shell history.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -43,7 +44,7 @@ Optional Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// 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 {
|
if len(args) != 1 && len(args) != 2 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -66,24 +67,24 @@ func (c *UserCheckPwCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := repo.User(domainName, userName)
|
user, err := repo.User(domainName, userName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", mailfull.ErrUserNotExist)
|
c.Meta.Errorf("%v\n", mailfull.ErrUserNotExist)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
input, err1 := c.UI.AskSecret(fmt.Sprintf("Enter password for %s:", address))
|
input, err := c.UI.AskSecret(fmt.Sprintf("Enter password for %s:", address))
|
||||||
if err1 != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err1)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,27 +1,28 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserDelCommand represents a UserDelCommand.
|
// CmdUserDel represents a CmdUserDel.
|
||||||
type UserDelCommand struct {
|
type CmdUserDel struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *UserDelCommand) Synopsis() string {
|
func (c *CmdUserDel) Synopsis() string {
|
||||||
return "Delete and backup a user."
|
return "Delete and backup a user."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *UserDelCommand) Help() string {
|
func (c *CmdUserDel) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s address
|
%s %s [-n] address
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -29,6 +30,10 @@ Description:
|
|||||||
Required Args:
|
Required Args:
|
||||||
address
|
address
|
||||||
The email address that you want to delete.
|
The email address that you want to delete.
|
||||||
|
|
||||||
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -37,7 +42,13 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *UserDelCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -55,24 +66,25 @@ func (c *UserDelCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if userName == "postmaster" {
|
||||||
|
c.Meta.Errorf("Cannot delete postmaster.\n")
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo.UserRemove(domainName, userName); err != nil {
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,28 +1,29 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
"github.com/jsimonetti/pwscheme/ssha"
|
"github.com/jsimonetti/pwscheme/ssha"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserPasswdCommand represents a UserPasswdCommand.
|
// CmdUserPasswd represents a CmdUserPasswd.
|
||||||
type UserPasswdCommand struct {
|
type CmdUserPasswd struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *UserPasswdCommand) Synopsis() string {
|
func (c *CmdUserPasswd) Synopsis() string {
|
||||||
return "Update user's password."
|
return "Update user's password."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *UserPasswdCommand) Help() string {
|
func (c *CmdUserPasswd) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s address [password]
|
%s %s [-n] address [password]
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
%s
|
%s
|
||||||
@@ -32,9 +33,11 @@ Required Args:
|
|||||||
The email address that you want to update the password.
|
The email address that you want to update the password.
|
||||||
|
|
||||||
Optional Args:
|
Optional Args:
|
||||||
|
-n
|
||||||
|
Don't update databases.
|
||||||
password
|
password
|
||||||
Specify the password instead of your typing.
|
Specify the password instead of your typing.
|
||||||
This option is not recommended because the password will be visible in your shell history.
|
This option is NOT recommended because the password will be visible in your shell history.
|
||||||
`,
|
`,
|
||||||
c.CmdName, c.SubCmdName,
|
c.CmdName, c.SubCmdName,
|
||||||
c.Synopsis())
|
c.Synopsis())
|
||||||
@@ -43,7 +46,13 @@ Optional Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// Run runs the command and returns the exit status.
|
||||||
func (c *UserPasswdCommand) Run(args []string) int {
|
func (c *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 {
|
if len(args) != 1 && len(args) != 2 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -66,33 +75,33 @@ func (c *UserPasswdCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := repo.User(domainName, userName)
|
user, err := repo.User(domainName, userName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", mailfull.ErrUserNotExist)
|
c.Meta.Errorf("%v\n", mailfull.ErrUserNotExist)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
input1, err1 := c.UI.AskSecret(fmt.Sprintf("Enter new password for %s:", address))
|
input1, err := c.UI.AskSecret(fmt.Sprintf("Enter new password for %s:", address))
|
||||||
if err1 != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err1)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
input2, err2 := c.UI.AskSecret("Retype new password:")
|
input2, err := c.UI.AskSecret("Retype new password:")
|
||||||
if err2 != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err2)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
if input1 != input2 {
|
if input1 != input2 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] inputs do not match.\n")
|
c.Meta.Errorf("inputs do not match.\n")
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
rawPassword = input1
|
rawPassword = input1
|
||||||
@@ -100,9 +109,9 @@ func (c *UserPasswdCommand) Run(args []string) int {
|
|||||||
|
|
||||||
hashedPassword := mailfull.NeverMatchHashedPassword
|
hashedPassword := mailfull.NeverMatchHashedPassword
|
||||||
if rawPassword != "" {
|
if rawPassword != "" {
|
||||||
str, errHash := ssha.Generate(rawPassword, 4)
|
str, err := ssha.Generate(rawPassword, 4)
|
||||||
if errHash != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", errHash)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
hashedPassword = str
|
hashedPassword = str
|
||||||
@@ -111,19 +120,15 @@ func (c *UserPasswdCommand) Run(args []string) int {
|
|||||||
user.SetHashedPassword(hashedPassword)
|
user.SetHashedPassword(hashedPassword)
|
||||||
|
|
||||||
if err := repo.UserUpdate(domainName, user); err != nil {
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mailData, err := repo.MailData()
|
if noCommit {
|
||||||
if err != nil {
|
return 0
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
if err = repo.GenerateDatabases(); err != nil {
|
||||||
err = repo.GenerateDatabases(mailData)
|
c.Meta.Errorf("%v\n", err)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,24 +1,25 @@
|
|||||||
package command
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UsersCommand represents a UsersCommand.
|
// CmdUsers represents a CmdUsers.
|
||||||
type UsersCommand struct {
|
type CmdUsers struct {
|
||||||
Meta
|
cmd.Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
// Synopsis returns a one-line synopsis.
|
||||||
func (c *UsersCommand) Synopsis() string {
|
func (c *CmdUsers) Synopsis() string {
|
||||||
return "Show users."
|
return "Show users."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help returns long-form help text.
|
// Help returns long-form help text.
|
||||||
func (c *UsersCommand) Help() string {
|
func (c *CmdUsers) Help() string {
|
||||||
txt := fmt.Sprintf(`
|
txt := fmt.Sprintf(`
|
||||||
Usage:
|
Usage:
|
||||||
%s %s domain
|
%s %s domain
|
||||||
@@ -37,7 +38,7 @@ Required Args:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command and returns the exit status.
|
// 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 {
|
if len(args) != 1 {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
fmt.Fprintf(c.UI.ErrorWriter, "%v\n", c.Help())
|
||||||
return 1
|
return 1
|
||||||
@@ -47,16 +48,16 @@ func (c *UsersCommand) Run(args []string) int {
|
|||||||
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
repo, err := mailfull.OpenRepository(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
users, err := repo.Users(targetDomainName)
|
users, err := repo.Users(targetDomainName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
c.Meta.Errorf("%v\n", err)
|
||||||
return 1
|
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 {
|
for _, user := range users {
|
||||||
fmt.Fprintf(c.UI.Writer, "%s\n", user.Name())
|
fmt.Fprintf(c.UI.Writer, "%s\n", user.Name())
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DomainsCommand represents a DomainsCommand.
|
|
||||||
type DomainsCommand struct {
|
|
||||||
Meta
|
|
||||||
}
|
|
||||||
|
|
||||||
// Synopsis returns a one-line synopsis.
|
|
||||||
func (c *DomainsCommand) Synopsis() string {
|
|
||||||
return "Show domains."
|
|
||||||
}
|
|
||||||
|
|
||||||
// Help returns long-form help text.
|
|
||||||
func (c *DomainsCommand) 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 *DomainsCommand) Run(args []string) int {
|
|
||||||
repo, err := mailfull.OpenRepository(".")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
domains, err := repo.Domains()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(c.UI.ErrorWriter, "[ERR] %v\n", err)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
sort.Sort(mailfull.DomainSlice(domains))
|
|
||||||
|
|
||||||
for _, domain := range domains {
|
|
||||||
fmt.Fprintf(c.UI.Writer, "%s\n", domain.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -4,12 +4,15 @@ Command mailfull is a CLI application using the mailfull package.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/directorz/mailfull-go"
|
"github.com/directorz/mailfull-go"
|
||||||
"github.com/directorz/mailfull-go/cmd/mailfull/command"
|
"github.com/directorz/mailfull-go/cmd"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,8 +23,9 @@ var (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
if gittag != "" {
|
if gittag != "" {
|
||||||
version = version + "-" + gittag
|
version += "-" + gittag
|
||||||
}
|
}
|
||||||
|
version += fmt.Sprintf(" (built with %s)", runtime.Version())
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -31,7 +35,7 @@ func main() {
|
|||||||
Args: os.Args[1:],
|
Args: os.Args[1:],
|
||||||
}
|
}
|
||||||
|
|
||||||
meta := command.Meta{
|
meta := cmd.Meta{
|
||||||
UI: &cli.BasicUi{
|
UI: &cli.BasicUi{
|
||||||
Reader: os.Stdin,
|
Reader: os.Stdin,
|
||||||
Writer: os.Stdout,
|
Writer: os.Stdout,
|
||||||
@@ -44,87 +48,95 @@ func main() {
|
|||||||
c.Commands = map[string]cli.CommandFactory{
|
c.Commands = map[string]cli.CommandFactory{
|
||||||
"init": func() (cli.Command, error) {
|
"init": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.InitCommand{Meta: meta}, nil
|
return &CmdInit{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"genconfig": func() (cli.Command, error) {
|
"genconfig": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.GenConfigCommand{Meta: meta}, nil
|
return &CmdGenConfig{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"domains": func() (cli.Command, error) {
|
"domains": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.DomainsCommand{Meta: meta}, nil
|
return &CmdDomains{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"domainadd": func() (cli.Command, error) {
|
"domainadd": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.DomainAddCommand{Meta: meta}, nil
|
return &CmdDomainAdd{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"domaindel": func() (cli.Command, error) {
|
"domaindel": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
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 &CmdDomainDisable{Meta: meta}, nil
|
||||||
|
},
|
||||||
|
"domainenable": func() (cli.Command, error) {
|
||||||
|
meta.SubCmdName = c.Subcommand()
|
||||||
|
return &CmdDomainEnable{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"aliasdomains": func() (cli.Command, error) {
|
"aliasdomains": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.AliasDomainsCommand{Meta: meta}, nil
|
return &CmdAliasDomains{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"aliasdomainadd": func() (cli.Command, error) {
|
"aliasdomainadd": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.AliasDomainAddCommand{Meta: meta}, nil
|
return &CmdAliasDomainAdd{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"aliasdomaindel": func() (cli.Command, error) {
|
"aliasdomaindel": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.AliasDomainDelCommand{Meta: meta}, nil
|
return &CmdAliasDomainDel{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"users": func() (cli.Command, error) {
|
"users": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.UsersCommand{Meta: meta}, nil
|
return &CmdUsers{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"useradd": func() (cli.Command, error) {
|
"useradd": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.UserAddCommand{Meta: meta}, nil
|
return &CmdUserAdd{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"userdel": func() (cli.Command, error) {
|
"userdel": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.UserDelCommand{Meta: meta}, nil
|
return &CmdUserDel{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"userpasswd": func() (cli.Command, error) {
|
"userpasswd": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.UserPasswdCommand{Meta: meta}, nil
|
return &CmdUserPasswd{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"usercheckpw": func() (cli.Command, error) {
|
"usercheckpw": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.UserCheckPwCommand{Meta: meta}, nil
|
return &CmdUserCheckPw{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"aliasusers": func() (cli.Command, error) {
|
"aliasusers": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.AliasUsersCommand{Meta: meta}, nil
|
return &CmdAliasUsers{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"aliasuseradd": func() (cli.Command, error) {
|
"aliasuseradd": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.AliasUserAddCommand{Meta: meta}, nil
|
return &CmdAliasUserAdd{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"aliasusermod": func() (cli.Command, error) {
|
"aliasusermod": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.AliasUserModCommand{Meta: meta}, nil
|
return &CmdAliasUserMod{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"aliasuserdel": func() (cli.Command, error) {
|
"aliasuserdel": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.AliasUserDelCommand{Meta: meta}, nil
|
return &CmdAliasUserDel{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"catchall": func() (cli.Command, error) {
|
"catchall": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.CatchAllCommand{Meta: meta}, nil
|
return &CmdCatchAll{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"catchallset": func() (cli.Command, error) {
|
"catchallset": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.CatchAllSetCommand{Meta: meta}, nil
|
return &CmdCatchAllSet{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"catchallunset": func() (cli.Command, error) {
|
"catchallunset": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.CatchAllUnsetCommand{Meta: meta}, nil
|
return &CmdCatchAllUnset{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
"commit": func() (cli.Command, error) {
|
"commit": func() (cli.Command, error) {
|
||||||
meta.SubCmdName = c.Subcommand()
|
meta.SubCmdName = c.Subcommand()
|
||||||
return &command.CommitCommand{Meta: meta}, nil
|
return &CmdCommit{Meta: meta}, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,3 +147,17 @@ func main() {
|
|||||||
|
|
||||||
os.Exit(exitCode)
|
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
20
cmd/meta.go
Normal 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...)
|
||||||
|
}
|
||||||
1
const.go
1
const.go
@@ -5,6 +5,7 @@ const (
|
|||||||
DirNameConfig = ".mailfull"
|
DirNameConfig = ".mailfull"
|
||||||
FileNameConfig = "config"
|
FileNameConfig = "config"
|
||||||
|
|
||||||
|
FileNameDomainDisable = ".vdomaindisable"
|
||||||
FileNameAliasDomains = ".valiasdomains"
|
FileNameAliasDomains = ".valiasdomains"
|
||||||
FileNameUsersPassword = ".vpasswd"
|
FileNameUsersPassword = ".vpasswd"
|
||||||
FileNameUserForwards = ".forward"
|
FileNameUserForwards = ".forward"
|
||||||
|
|||||||
131
database.go
131
database.go
@@ -9,33 +9,84 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenerateDatabases generates databases from the MailData directory.
|
// repoData represents a repoData.
|
||||||
func (r *Repository) GenerateDatabases(md *MailData) error {
|
type repoData struct {
|
||||||
sort.Sort(DomainSlice(md.Domains))
|
Domains []*Domain
|
||||||
sort.Sort(AliasDomainSlice(md.AliasDomains))
|
AliasDomains []*AliasDomain
|
||||||
|
}
|
||||||
|
|
||||||
for _, domain := range md.Domains {
|
// repoData returns a repoData.
|
||||||
sort.Sort(UserSlice(domain.Users))
|
func (r *Repository) repoData() (*repoData, error) {
|
||||||
sort.Sort(AliasUserSlice(domain.AliasUsers))
|
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
|
// Generate files
|
||||||
if err := r.generateDbDomains(md); err != nil {
|
if err := r.generateDbDomains(rd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := r.generateDbDestinations(md); err != nil {
|
if err := r.generateDbDestinations(rd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := r.generateDbMaildirs(md); err != nil {
|
if err := r.generateDbMaildirs(rd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := r.generateDbLocaltable(md); err != nil {
|
if err := r.generateDbLocaltable(rd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := r.generateDbForwards(md); err != nil {
|
if err := r.generateDbForwards(rd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := r.generateDbPasswords(md); err != nil {
|
if err := r.generateDbPasswords(rd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +110,7 @@ func (r *Repository) GenerateDatabases(md *MailData) error {
|
|||||||
return nil
|
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))
|
dbDomains, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbDomains))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -69,13 +120,17 @@ func (r *Repository) generateDbDomains(md *MailData) error {
|
|||||||
}
|
}
|
||||||
defer dbDomains.Close()
|
defer dbDomains.Close()
|
||||||
|
|
||||||
for _, domain := range md.Domains {
|
for _, domain := range rd.Domains {
|
||||||
|
if domain.Disabled() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := fmt.Fprintf(dbDomains, "%s virtual\n", domain.Name()); err != nil {
|
if _, err := fmt.Fprintf(dbDomains, "%s virtual\n", domain.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, aliasDomain := range md.AliasDomains {
|
for _, aliasDomain := range rd.AliasDomains {
|
||||||
if _, err := fmt.Fprintf(dbDomains, "%s virtual\n", aliasDomain.Name()); err != nil {
|
if _, err := fmt.Fprintf(dbDomains, "%s virtual\n", aliasDomain.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -84,7 +139,7 @@ func (r *Repository) generateDbDomains(md *MailData) error {
|
|||||||
return nil
|
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))
|
dbDestinations, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbDestinations))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -94,7 +149,11 @@ func (r *Repository) generateDbDestinations(md *MailData) error {
|
|||||||
}
|
}
|
||||||
defer dbDestinations.Close()
|
defer dbDestinations.Close()
|
||||||
|
|
||||||
for _, domain := range md.Domains {
|
for _, domain := range rd.Domains {
|
||||||
|
if domain.Disabled() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// ho-ge.example.com -> ho_ge.example.com
|
// ho-ge.example.com -> ho_ge.example.com
|
||||||
underscoredDomainName := domain.Name()
|
underscoredDomainName := domain.Name()
|
||||||
underscoredDomainName = strings.Replace(underscoredDomainName, `-`, `_`, -1)
|
underscoredDomainName = strings.Replace(underscoredDomainName, `-`, `_`, -1)
|
||||||
@@ -115,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 aliasDomain.Target() == domain.Name() {
|
||||||
if _, err := fmt.Fprintf(dbDestinations, "%s@%s %s@%s\n", userName, aliasDomain.Name(), user.Name(), domain.Name()); err != nil {
|
if _, err := fmt.Fprintf(dbDestinations, "%s@%s %s@%s\n", userName, aliasDomain.Name(), user.Name(), domain.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -129,7 +188,7 @@ func (r *Repository) generateDbDestinations(md *MailData) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, aliasDomain := range md.AliasDomains {
|
for _, aliasDomain := range rd.AliasDomains {
|
||||||
if aliasDomain.Target() == domain.Name() {
|
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 {
|
if _, err := fmt.Fprintf(dbDestinations, "%s@%s %s@%s\n", aliasUser.Name(), aliasDomain.Name(), aliasUser.Name(), domain.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -142,7 +201,7 @@ func (r *Repository) generateDbDestinations(md *MailData) error {
|
|||||||
return nil
|
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))
|
dbMaildirs, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbMaildirs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -152,7 +211,11 @@ func (r *Repository) generateDbMaildirs(md *MailData) error {
|
|||||||
}
|
}
|
||||||
defer dbMaildirs.Close()
|
defer dbMaildirs.Close()
|
||||||
|
|
||||||
for _, domain := range md.Domains {
|
for _, domain := range rd.Domains {
|
||||||
|
if domain.Disabled() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
for _, user := range domain.Users {
|
for _, user := range domain.Users {
|
||||||
if _, err := fmt.Fprintf(dbMaildirs, "%s@%s %s/%s/Maildir/\n", user.Name(), domain.Name(), domain.Name(), user.Name()); err != nil {
|
if _, err := fmt.Fprintf(dbMaildirs, "%s@%s %s/%s/Maildir/\n", user.Name(), domain.Name(), domain.Name(), user.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -163,7 +226,7 @@ func (r *Repository) generateDbMaildirs(md *MailData) error {
|
|||||||
return nil
|
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))
|
dbLocaltable, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbLocaltable))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -173,7 +236,11 @@ func (r *Repository) generateDbLocaltable(md *MailData) error {
|
|||||||
}
|
}
|
||||||
defer dbLocaltable.Close()
|
defer dbLocaltable.Close()
|
||||||
|
|
||||||
for _, domain := range md.Domains {
|
for _, domain := range rd.Domains {
|
||||||
|
if domain.Disabled() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// ho-ge.example.com -> ho_ge\.example\.com
|
// ho-ge.example.com -> ho_ge\.example\.com
|
||||||
escapedDomainName := domain.Name()
|
escapedDomainName := domain.Name()
|
||||||
escapedDomainName = strings.Replace(escapedDomainName, `-`, `_`, -1)
|
escapedDomainName = strings.Replace(escapedDomainName, `-`, `_`, -1)
|
||||||
@@ -187,7 +254,7 @@ func (r *Repository) generateDbLocaltable(md *MailData) error {
|
|||||||
return nil
|
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))
|
dbForwards, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbForwards))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -197,7 +264,11 @@ func (r *Repository) generateDbForwards(md *MailData) error {
|
|||||||
}
|
}
|
||||||
defer dbForwards.Close()
|
defer dbForwards.Close()
|
||||||
|
|
||||||
for _, domain := range md.Domains {
|
for _, domain := range rd.Domains {
|
||||||
|
if domain.Disabled() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// ho-ge.example.com -> ho_ge.example.com
|
// ho-ge.example.com -> ho_ge.example.com
|
||||||
underscoredDomainName := domain.Name()
|
underscoredDomainName := domain.Name()
|
||||||
underscoredDomainName = strings.Replace(underscoredDomainName, `-`, `_`, -1)
|
underscoredDomainName = strings.Replace(underscoredDomainName, `-`, `_`, -1)
|
||||||
@@ -223,7 +294,7 @@ func (r *Repository) generateDbForwards(md *MailData) error {
|
|||||||
return nil
|
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))
|
dbPasswords, err := os.Create(filepath.Join(r.DirDatabasePath, FileNameDbPasswords))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -233,7 +304,11 @@ func (r *Repository) generateDbPasswords(md *MailData) error {
|
|||||||
}
|
}
|
||||||
defer dbPasswords.Close()
|
defer dbPasswords.Close()
|
||||||
|
|
||||||
for _, domain := range md.Domains {
|
for _, domain := range rd.Domains {
|
||||||
|
if domain.Disabled() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
for _, user := range domain.Users {
|
for _, user := range domain.Users {
|
||||||
if _, err := fmt.Fprintf(dbPasswords, "%s@%s:%s\n", user.Name(), domain.Name(), user.HashedPassword()); err != nil {
|
if _, err := fmt.Fprintf(dbPasswords, "%s@%s:%s\n", user.Name(), domain.Name(), user.HashedPassword()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
5
doc/README.md
Normal file
5
doc/README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Documentation
|
||||||
|
=============
|
||||||
|
|
||||||
|
- [Configuration](configuration.md)
|
||||||
|
- [Migrating from mailfull](migrating_from_mailfull.md)
|
||||||
12
doc/configuration.md
Normal file
12
doc/configuration.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
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 |
|
||||||
24
doc/migrating_from_mailfull.md
Normal file
24
doc/migrating_from_mailfull.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
Migrating from mailfull
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Migrating from [directorz/mailfull](https://github.com/directorz/mailfull)
|
||||||
|
|
||||||
|
Change directory to Mailfull directory.
|
||||||
|
|
||||||
|
```
|
||||||
|
# su - mailfull
|
||||||
|
$ cd /home/mailfull
|
||||||
|
```
|
||||||
|
|
||||||
|
Initialize a directory as a Mailfull repository.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mailfull init
|
||||||
|
```
|
||||||
|
|
||||||
|
Delete unnecessary files.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ rm -rf .git .gitignore bin docs lib README.md README.ja.md
|
||||||
|
$ find domains -maxdepth 2 -name '.vforward' | xargs rm -f
|
||||||
|
```
|
||||||
128
domain.go
128
domain.go
@@ -11,36 +11,49 @@ import (
|
|||||||
// Domain represents a Domain.
|
// Domain represents a Domain.
|
||||||
type Domain struct {
|
type Domain struct {
|
||||||
name string
|
name string
|
||||||
|
disabled bool
|
||||||
Users []*User
|
Users []*User
|
||||||
AliasUsers []*AliasUser
|
AliasUsers []*AliasUser
|
||||||
CatchAllUser *CatchAllUser
|
CatchAllUser *CatchAllUser
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// NewDomain creates a new Domain instance.
|
||||||
func NewDomain(name string) (*Domain, error) {
|
func NewDomain(name string) (*Domain, error) {
|
||||||
if !validDomainName(name) {
|
d := &Domain{}
|
||||||
return nil, ErrInvalidDomainName
|
|
||||||
}
|
|
||||||
|
|
||||||
d := &Domain{
|
if err := d.setName(name); err != nil {
|
||||||
name: name,
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setName sets the name.
|
||||||
|
func (d *Domain) setName(name string) error {
|
||||||
|
if !validDomainName(name) {
|
||||||
|
return ErrInvalidDomainName
|
||||||
|
}
|
||||||
|
|
||||||
|
d.name = name
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Name returns name.
|
// Name returns name.
|
||||||
func (d *Domain) Name() string {
|
func (d *Domain) Name() string {
|
||||||
return d.name
|
return d.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDisabled disables the Domain if the input is true.
|
||||||
|
func (d *Domain) SetDisabled(disabled bool) {
|
||||||
|
d.disabled = disabled
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disabled returns true if the Domain is disabled.
|
||||||
|
func (d *Domain) Disabled() bool {
|
||||||
|
return d.disabled
|
||||||
|
}
|
||||||
|
|
||||||
// Domains returns a Domain slice.
|
// Domains returns a Domain slice.
|
||||||
func (r *Repository) Domains() ([]*Domain, error) {
|
func (r *Repository) Domains() ([]*Domain, error) {
|
||||||
fileInfos, err := ioutil.ReadDir(r.DirMailDataPath)
|
fileInfos, err := ioutil.ReadDir(r.DirMailDataPath)
|
||||||
@@ -62,6 +75,12 @@ func (r *Repository) Domains() ([]*Domain, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disabled, err := r.domainDisabled(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
domain.SetDisabled(disabled)
|
||||||
|
|
||||||
domains = append(domains, domain)
|
domains = append(domains, domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,9 +113,38 @@ func (r *Repository) Domain(domainName string) (*Domain, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disabled, err := r.domainDisabled(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
domain.SetDisabled(disabled)
|
||||||
|
|
||||||
return domain, nil
|
return domain, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// domainDisabled returns true if the input Domain is disabled.
|
||||||
|
func (r *Repository) domainDisabled(domainName string) (bool, error) {
|
||||||
|
if !validDomainName(domainName) {
|
||||||
|
return false, ErrInvalidDomainName
|
||||||
|
}
|
||||||
|
|
||||||
|
fi, err := os.Stat(filepath.Join(r.DirMailDataPath, domainName, FileNameDomainDisable))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if err.(*os.PathError).Err == syscall.ENOENT {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.IsDir() {
|
||||||
|
return false, ErrInvalidFormatDomainDisabled
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
// DomainCreate creates the input Domain.
|
// DomainCreate creates the input Domain.
|
||||||
func (r *Repository) DomainCreate(domain *Domain) error {
|
func (r *Repository) DomainCreate(domain *Domain) error {
|
||||||
existDomain, err := r.Domain(domain.Name())
|
existDomain, err := r.Domain(domain.Name())
|
||||||
@@ -150,6 +198,29 @@ func (r *Repository) DomainCreate(domain *Domain) error {
|
|||||||
}
|
}
|
||||||
catchAllUserFile.Close()
|
catchAllUserFile.Close()
|
||||||
|
|
||||||
|
if domain.Disabled() {
|
||||||
|
if err := r.writeDomainDisabledFile(domain.Name(), domain.Disabled()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainUpdate updates the input Domain.
|
||||||
|
func (r *Repository) DomainUpdate(domain *Domain) error {
|
||||||
|
existDomain, err := r.Domain(domain.Name())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existDomain == nil {
|
||||||
|
return ErrDomainNotExist
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.writeDomainDisabledFile(domain.Name(), domain.Disabled()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,3 +253,36 @@ func (r *Repository) DomainRemove(domainName string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeDomainDisabledFile creates/removes the disabled file.
|
||||||
|
func (r *Repository) writeDomainDisabledFile(domainName string, disabled bool) error {
|
||||||
|
if !validDomainName(domainName) {
|
||||||
|
return ErrInvalidDomainName
|
||||||
|
}
|
||||||
|
|
||||||
|
nowDisabled, err := r.domainDisabled(domainName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
domainDisabledFileName := filepath.Join(r.DirMailDataPath, domainName, FileNameDomainDisable)
|
||||||
|
|
||||||
|
if !nowDisabled && disabled {
|
||||||
|
file, err := os.OpenFile(domainDisabledFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := file.Chown(r.uid, r.gid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
if nowDisabled && !disabled {
|
||||||
|
if err := os.Remove(domainDisabledFileName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ smtpd_sasl_path = private/auth
|
|||||||
smtpd_tls_cert_file = /etc/pki/dovecot/certs/dovecot.pem
|
smtpd_tls_cert_file = /etc/pki/dovecot/certs/dovecot.pem
|
||||||
smtpd_tls_key_file = /etc/pki/dovecot/private/dovecot.pem
|
smtpd_tls_key_file = /etc/pki/dovecot/private/dovecot.pem
|
||||||
#smtpd_tls_CAfile =
|
#smtpd_tls_CAfile =
|
||||||
smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_scache
|
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
|
||||||
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
|
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
|
||||||
|
|
||||||
smtp_tls_security_level = may
|
smtp_tls_security_level = may
|
||||||
|
|||||||
47
maildata.go
47
maildata.go
@@ -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
|
|
||||||
}
|
|
||||||
@@ -34,9 +34,10 @@ var (
|
|||||||
ErrAliasUserNotExist = errors.New("AliasUser: not exist")
|
ErrAliasUserNotExist = errors.New("AliasUser: not exist")
|
||||||
ErrAliasUserAlreadyExist = errors.New("AliasUser: already exist")
|
ErrAliasUserAlreadyExist = errors.New("AliasUser: already exist")
|
||||||
|
|
||||||
ErrInvalidFormatUsersPassword = errors.New("User: password file invalid format")
|
ErrInvalidFormatDomainDisabled = errors.New("Domain: disabled file invalid format")
|
||||||
ErrInvalidFormatAliasDomain = errors.New("AliasDomain: file invalid format")
|
ErrInvalidFormatUsersPassword = errors.New("User: password file invalid format")
|
||||||
ErrInvalidFormatAliasUsers = errors.New("AliasUsers: file invalid format")
|
ErrInvalidFormatAliasDomain = errors.New("AliasDomain: file invalid format")
|
||||||
|
ErrInvalidFormatAliasUsers = errors.New("AliasUsers: file invalid format")
|
||||||
)
|
)
|
||||||
|
|
||||||
// RepositoryConfig is used to configure a Repository.
|
// RepositoryConfig is used to configure a Repository.
|
||||||
@@ -126,10 +127,10 @@ func OpenRepository(basePath string) (*Repository, error) {
|
|||||||
for {
|
for {
|
||||||
configDirPath := filepath.Join(rootPath, DirNameConfig)
|
configDirPath := filepath.Join(rootPath, DirNameConfig)
|
||||||
|
|
||||||
fi, errStat := os.Stat(configDirPath)
|
fi, err := os.Stat(configDirPath)
|
||||||
if errStat != nil {
|
if err != nil {
|
||||||
if errStat.(*os.PathError).Err != syscall.ENOENT {
|
if err.(*os.PathError).Err != syscall.ENOENT {
|
||||||
return nil, errStat
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if fi.IsDir() {
|
if fi.IsDir() {
|
||||||
|
|||||||
10
user.go
10
user.go
@@ -19,13 +19,6 @@ type User struct {
|
|||||||
forwards []string
|
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.
|
// NewUser creates a new User instance.
|
||||||
func NewUser(name, hashedPassword string, forwards []string) (*User, error) {
|
func NewUser(name, hashedPassword string, forwards []string) (*User, error) {
|
||||||
u := &User{}
|
u := &User{}
|
||||||
@@ -107,6 +100,9 @@ func (r *Repository) Users(domainName string) ([]*User, error) {
|
|||||||
|
|
||||||
forwards, err := r.userForwards(domainName, name)
|
forwards, err := r.userForwards(domainName, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == ErrInvalidUserName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
valid.go
8
valid.go
@@ -33,20 +33,20 @@ func validAliasDomainTarget(target string) bool {
|
|||||||
|
|
||||||
// validUserName returns true if the input is correct format.
|
// validUserName returns true if the input is correct format.
|
||||||
func validUserName(name string) bool {
|
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.
|
// validAliasUserName returns true if the input is correct format.
|
||||||
func validAliasUserName(name string) bool {
|
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.
|
// validAliasUserTarget returns true if the input is correct format.
|
||||||
func validAliasUserTarget(target string) bool {
|
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.
|
// validCatchAllUserName returns true if the input is correct format.
|
||||||
func validCatchAllUserName(name string) bool {
|
func validCatchAllUserName(name string) bool {
|
||||||
return regexp.MustCompile(`^[^\s@]+$`).MatchString(name)
|
return regexp.MustCompile(`^[^\.\s@][^\s@]+$`).MatchString(name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package mailfull
|
package mailfull
|
||||||
|
|
||||||
// Version is a version number.
|
// Version is a version number.
|
||||||
const Version = "0.0.2"
|
const Version = "v1.0.3"
|
||||||
|
|||||||
Reference in New Issue
Block a user