mailwebadmin

package module
v0.0.0-...-107e66b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2017 License: MIT Imports: 28 Imported by: 0

README

mailwebadmin

mailwebadmin is a software used to administrate a mailserver (create accounts, delete accounts, administrate aliases, change passwords and so on). It requires a setup as described here, with one important difference: Currently only SHA-512 is supported and not SHA-256, but this is something that should be really easy to fix. If you want to use that feel free to contact me or write the code yourself and use a pull request.

The software is written in Go, but requires the Linux crypt(3). I've tested it on Debian and Ubuntu and it worked fine (sadly enough alpine does not work). It is also possible that it works under Windows, but I've never tested it. The wrapper can be found here.

The preferred way to install it is by using docker, there is a docker file (in this repository) and you can also pull directly from Docker Hub.

Information about the installation can be found on the project Wiki, the source code documentation is also available on GoDoc.

Current Version

The current version is 1.0, it hasn't been properly tested, but it should work (though it would be nice if someone reviews it especially regarding security).

License

The software is distributed under the MIT License, see the license page in the wiki for more information.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidEmail = errors.New("Invalid Email address")

ErrInvalidEmail is the error returned if an string is not a valid email address.

Functions

func AddAlias

func AddAlias(appContext *MailAppContext, source, destination string) (int64, error)

AddAlias adds a new alias, it returns the id of the alias in the table and any error that occcurred.

func AddMailUser

func AddMailUser(appContext *MailAppContext, email, plaintextPW string) (int64, error)

AddMailUser adds a new mail user. On success it returns the insert id and nil, on failure -1 and an error != nil.

func AddVirtualDomain

func AddVirtualDomain(appContext *MailAppContext, domain string) (int64, error)

AddVirtualDomain adds the domain to the database.

func BootstrapAdminsTemplate

func BootstrapAdminsTemplate() *template.Template

BootstrapAdminsTemplate is the template for the admins page.

func BootstrapAliasesTemplate

func BootstrapAliasesTemplate() *template.Template

BootstrapAliasesTemplate is the template for the alias page.

func BootstrapChangePWTemplate

func BootstrapChangePWTemplate() *template.Template

BootstrapChangePWTemplate is the template for the change email password site.

func BootstrapDomainsTemplate

func BootstrapDomainsTemplate() *template.Template

BootstrapDomainsTemplate is the template for the domains page.

func BootstrapLicenseTemplate

func BootstrapLicenseTemplate() *template.Template

BootstrapLicenseTemplate is the template for the license template.

func BootstrapLoginTemplate

func BootstrapLoginTemplate() *template.Template

BootstrapLoginTemplate is the template for the login page.

func BootstrapUsersTemplate

func BootstrapUsersTemplate() *template.Template

BootstrapUsersTemplate is the template for the users page.

func ChangeSinglePasswordHandler

func ChangeSinglePasswordHandler(appContext *MailAppContext, w http.ResponseWriter, r *http.Request) error

ChangeSinglePasswordHandler returns on get the template for changing a single password (RenderChangePWTemplate) and on post calls ChangeSinglePw to update te password.

func ChangeSinglePw

func ChangeSinglePw(appContext *MailAppContext, w http.ResponseWriter, r *http.Request) error

ChangeSinglePw reads a JSON encoded map from the body, it must have the form: {'mail': <Mail>, 'old_password': <Old>, 'new_password': <New>} It compares the old password with the one in the database, if this is not correct or the email doesn't exist it responds with a 400. If the password is correct the password gets updated.

func ChangeUserPassword

func ChangeUserPassword(appContext *MailAppContext, emailID int64, plaintextPW string) error

ChangeUserPassword changes the password for the user with the given id, it returns an error != nil if something went wrong.

func CheckLogin

func CheckLogin(appcontext *MailAppContext, w http.ResponseWriter, r *http.Request) error

CheckLogin checks the login data contained in the body of the request. The body must be a JSON object of the following form: {"username": <username>, "password": <password>, "remember-me": bool} It returns a 400 error if the syntax is wrong. If the login is correct it will create an auth session for the user, set the MaxAge field of the session etc. If the login succeeds it will return a 302 redirect to /. If the login fails it will return a 400.

func DelAlias

func DelAlias(appContext *MailAppContext, aliasID int64) error

DelAlias deletes the alias with the given id.

func DelMailUser

func DelMailUser(appContext *MailAppContext, emailID int64) error

DelMailUser removes the user with the given id.

func DeleteVirtualDomain

func DeleteVirtualDomain(appContext *MailAppContext, domainID int64) error

DeleteVirtualDomain deletes the domain. If the domain was not found no error is returned, but the information gets logged.

func GenDovecotSHA512

func GenDovecotSHA512(password string) (string, error)

GenDovecotSHA512 generates the SHA512 hash of the given password. TODO: Also support SHA256, should be very easy.

func GenKeyPair

func GenKeyPair() ([][]byte, error)

GenKeyPair generates a new auth-key, encryption-key pair.

func ListAdminsJSON

func ListAdminsJSON(appcontext *MailAppContext, w http.ResponseWriter, r *http.Request) error

ListAdminsJSON is the main handler for /api/admins. An admin is identified by the username, not an ID. On delete all sessions for the user will be deleted as well.

func ListAliasesJSON

func ListAliasesJSON(appcontext *MailAppContext, w http.ResponseWriter, r *http.Request) error

ListAliasesJSON is the main handler for /api/aliases. It works nearly as ListDomainsJSON, which has more documentation ;).

func ListAllUsers

func ListAllUsers(appContext *MailAppContext, domainID int64) (map[string]*ListUserResult, error)

ListAllUsers lists all users for a given domain. The result maps the email to the ListUserResult for that mail. Again a domainID < 0 means "all domains".

func ListDomainsJSON

func ListDomainsJSON(appcontext *MailAppContext, w http.ResponseWriter, r *http.Request) error

ListDomainsJSON is the main handler for domains. It either renders the template on GET, creates a new domain on POST or deletes a domain on DELETE.

func ListUsersJSON

func ListUsersJSON(appcontext *MailAppContext, w http.ResponseWriter, r *http.Request) error

ListUsersJSON handles the /api/users domains. Works nearly as ListDomainsJSON.

func ListVirtualAliases

func ListVirtualAliases(appContext *MailAppContext, domainID int64) (map[int64]*Alias, error)

ListVirtualAliases lists all virtual aliases given an domainID. If domainID is < 0 it returns all entries (for all domains). The map contains entries of the form aliasID --> Alias.

func ListVirtualDomains

func ListVirtualDomains(appContext *MailAppContext) (map[int64]string, error)

ListVirtualDomains returns a map containing all virtual domains in the form id --> name.

func ListVirtualUsers

func ListVirtualUsers(appContext *MailAppContext, domainID int64) (map[int64]*VirtualUser, error)

func LoginPageHandler

func LoginPageHandler(appcontext *MailAppContext, w http.ResponseWriter, r *http.Request) error

LoginPageHandler is a handler that returns the login template for GET and uses CheckLogin for POST. All other methods will return a 400.

func Logout

func Logout(appcontext *MailAppContext, w http.ResponseWriter, r *http.Request) error

Logout will set the MaxAge of the session to -1 and thus destroy the session. It will also delete the session from the database.

func ParseMailParts

func ParseMailParts(email string) (string, string, error)

ParseMailParts splits an email address and returns the part before the @, the domain and an error if this is not possible.

func ReadKeyPairs

func ReadKeyPairs(path string) ([][]byte, error)

ReadKeyPairs reads the key pairs from the key files. It returns an error if there are not % 2 keys in the file or something during reading goes wrong.

func RenderAdminsTemplate

func RenderAdminsTemplate(appContext *MailAppContext, w http.ResponseWriter, r *http.Request) error

RenderAdminsTemplate renders the template appContext.Templates["admins"].

func RenderAliasesTemplate

func RenderAliasesTemplate(appContext *MailAppContext, w http.ResponseWriter, r *http.Request) error

RenderAliasesTemplate renders the template appContext.Templates["aliases"].

func RenderChangePWTemplate

func RenderChangePWTemplate(appContext *MailAppContext, w http.ResponseWriter, r *http.Request) error

RenderChangePWTemplate renders the template appContext.Templates["change-pw"]. It adds the csrf.TemplateTag to the context of the template.

func RenderDomainsTemplate

func RenderDomainsTemplate(appContext *MailAppContext, w http.ResponseWriter, r *http.Request) error

RenderDomainsTemplate renders the template appContext.Templates["domains"].

func RenderLicenseTemplate

func RenderLicenseTemplate(appContext *MailAppContext, w http.ResponseWriter, r *http.Request) error

RenderLicenseTemplate renders the template appContext.Templates["license"].

func RenderLoginTemplate

func RenderLoginTemplate(appContext *MailAppContext, w http.ResponseWriter, r *http.Request) error

RenderLoginTemplate renders the template stored in appContext.Templates["login"]. It adds the csrf.TemplateTag to the context of the template.

func RenderRootTemplate

func RenderRootTemplate(appContext *MailAppContext, w http.ResponseWriter, r *http.Request) error

RenderRootTemplate renders the template appContext.Templates["root"].

func RenderUsersTemplate

func RenderUsersTemplate(appContext *MailAppContext, w http.ResponseWriter, r *http.Request) error

RenderUsersTemplate renders the template appContext.Templates["users"].

func RootBootstrapTemplate

func RootBootstrapTemplate() *template.Template

RootBootstrapTemplate is the template for the main page (/).

func RootPageHandler

func RootPageHandler(appcontext *MailAppContext, w http.ResponseWriter, r *http.Request) error

RootPageHandler is a handler that returns the root page.

func StaticHandler

func StaticHandler() http.Handler

StaticHandler is a http handler that serves files in the static directory.

func WriteKeyPairs

func WriteKeyPairs(path string, keyPairs ...[]byte) error

WriteKeyPairs writes the key pairs to the file specified in path. All keys get base64 encoded.

Types

type Alias

type Alias struct {
	// DomainID is the domain id of the source mail.
	DomainID int64
	// Source and Dest are the source and destination email.
	Source, Dest string
}

Alias stores information about a virtual alias.

type AppHandleFunc

type AppHandleFunc func(appcontext *MailAppContext, w http.ResponseWriter, r *http.Request) error

AppHandleFunc is a type for functions that accept a context as well as the request and response writer. It can be used as a http handle func via MailAppHandler. An error returned by this function should be only internal server errors. All other errors should be handled inside the function and return a corresponding http response. If an internal server error occurs there should be no writes to the response. ServeHTTP will handle internal server errors.

func LoginRequired

func LoginRequired(f AppHandleFunc) AppHandleFunc

LoginRequired takes a handler function and returns a new handler function that first checks if the login is correct. It will return a 302 redirect to the login page if the user is not logged in. It will also check if the session has a remember-me set, and if it is not set update the session MaxAge to 0. An error while updating the session will not be returned as an error, but will be logged.

type ListUserResult

type ListUserResult struct {
	VirtualUser   *VirtualUser
	VirtualUserID int64
	AliasFor      map[int64]*Alias
}

ListUserResult stores information about users. This is: All virtual users and users that are only an alias for something else combined. The VirtualUser is set to nil if it is only an alias and the virtual user ID. Otherwise it contains the valid user information. Alias for contains all aliases in the form aliasID -> Alias.

func NewListResultForVirtualAlias

func NewListResultForVirtualAlias() *ListUserResult

NewListResultForVirtualAlias creates a new ListUserResult for a virtual alias. It sets VirtualUser to nil, VirtualUserID to -1 and creates an empty AliasFor map.

func NewListResultForVirtualUser

func NewListResultForVirtualUser(user *VirtualUser, virtualUserID int64) *ListUserResult

NewListResultForVirtualUser creates a new ListUserResult for a virtual user. AliasFor gets initialized to an empty map.

type MailAppContext

type MailAppContext struct {
	// DB is the database to work on.
	DB *sql.DB
	// ConfigDir is the directory containing the configuration files.
	ConfigDir string
	// Store is the session store to be used. It gets initialized after reading
	// the key file.
	Store sessions.Store
	// Logger is used to log messages.
	Logger *logrus.Logger
	// UserHandler is used to administer admin users.
	UserHandler goauth.UserHandler
	// SessionController is used to control the admin users sessions.
	SessionController *goauth.SessionController
	// Keys stores the keys used for the auth sessions, see
	// http://www.gorillatoolkit.org/pkg/sessions for more details.
	// We assume that we always have pairs of keys: auth-key and encryption-key.
	Keys [][]byte
	// Templates stores all templates for rendering the pages.
	// See the main file for all templates used.
	Templates map[string]*template.Template
	// DefaultSessionLifespan is the lifespan of a session for an admin user.
	DefaultSessionLifespan time.Duration
	// Port is the port to run on, defaults to 80.
	Port int
	// MailDir is the pattern that returns the path of a user / domain.
	// It must contain the placeholders %d that gets replaced by the domain
	// and %n that gets replaced by the user name.
	// It defaults to "/var/vmail/%d/%n".
	// If no username is given (i.e. we want the directory for a whole domain)
	// %n gets replaced by the empty string, so this must return a valid path.
	MailDir string
	// Delete is set to true if when deleting a domain / user from the database
	// the corresponding directories should be deleted as well.
	Delete bool
	// Backup is the directory where the backup files are stored.
	// If set to the empty string no backups will be created.
	// Otherwise backups (as zip files) are created inside this directory.
	// It defaults to the empty string.
	Backup string
}

MailAppContext stores all global options for all handlers.

func ParseConfig

func ParseConfig(configDir string, startDaemon bool) (*MailAppContext, error)

ParseConfig parses the configuration file (called mailconf in the config dir). It sets some values to a default value, connects to and initializes the database. It calls ReadOrCreateKeys. startDaemon is set to true if you want to start a daemon to delete invalid keys.

func (*MailAppContext) ReadOrCreateKeys

func (context *MailAppContext) ReadOrCreateKeys()

ReadOrCreateKeys either reads the key file or, if it doesn't exist, creates a key pair. contenxt.Keys are set to the keys read / created. If a key file (inside ConfigDir/keys) exists it must be a file with a key in each line. There must be pairs stored in the file: A list of auth-key encryption-key ... The auth-keys must be 64 byte long, the encryption keys 32 bytes long.

type MailAppHandler

type MailAppHandler struct {
	// MailAppContext is the context that stores things like global settings,
	// the database connection etc.
	*MailAppContext
	// contains filtered or unexported fields
}

MailAppHandler is the handler class for AppHandleFuncs. It can be used as http handler via ServeHTTP.

func NewMailAppHandler

func NewMailAppHandler(context *MailAppContext, f AppHandleFunc) *MailAppHandler

NewMailAppHandler returns a new MailAppHandler.

func (*MailAppHandler) ServeHTTP

func (handler *MailAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements the http handler interface. If will execute the handle function and check for an error. If an error is returned (this means an internal error occurred) it will reply with a 500 Internal Server Error.

type VirtualUser

type VirtualUser struct {
	// DomainID is the id for the domain stored in the database.
	DomainID int64
	// Mail is the user Email.
	Mail string
}

VirtualUser stores information about a virtual user, the mail address and the virtual domain id.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL