package module
Version: v0.0.0-...-f01fbcb Latest Latest

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

Go to latest
Published: Oct 18, 2022 License: MIT Imports: 28 Imported by: 0



GoDoc status

A simple and extensible webmail.


Assuming SRV DNS records are properly set up (see RFC 6186):

go run ./cmd/alps

To manually specify upstream servers:

go run ./cmd/alps imaps:// smtps://

Add -theme alps to use the alps theme. See docs/ for more information.

When developing themes and plugins, the script contrib/ can be used to automatically reload alps on file changes.


Send patches on the mailing list, report bugs on the issue tracker.






View Source
const PluginDir = "plugins"

PluginDir is the path to the plugins directory.


View Source
var (
	ErrSessionExpired      = errors.New("session expired")
	ErrAttachmentCacheSize = errors.New("Attachments on session exceed maximum file size")
View Source
var ErrNoStoreEntry = fmt.Errorf("alps: no such entry in store")

ErrNoStoreEntry is returned by Store.Get when the entry doesn't exist.


func RegisterPluginLoader

func RegisterPluginLoader(f PluginLoaderFunc)

RegisterPluginLoader registers a plugin loader. The loader will be called on server start-up and reload.


type Attachment

type Attachment struct {
	File *multipart.FileHeader
	Form *multipart.Form

type AuthError

type AuthError struct {
	// contains filtered or unexported fields

AuthError wraps an authentication error.

func (AuthError) Error

func (err AuthError) Error() string

type BaseRenderData

type BaseRenderData struct {
	GlobalData GlobalRenderData
	// additional plugin-specific data
	Extra map[string]interface{}

BaseRenderData is the base type for templates. It should be extended with additional template-specific fields:

type MyRenderData struct {
    // add additional fields here

func NewBaseRenderData

func NewBaseRenderData(ectx echo.Context) *BaseRenderData

NewBaseRenderData initializes a new BaseRenderData.

It can be used by routes to pre-fill the base data:

type MyRenderData struct {
    // add additional fields here

data := &MyRenderData{
    BaseRenderData: *alps.NewBaseRenderData(ctx),
    // other fields...

func (*BaseRenderData) Global

func (brd *BaseRenderData) Global() *GlobalRenderData

Global implements RenderData.

func (*BaseRenderData) WithTitle

func (brd *BaseRenderData) WithTitle(title string) *BaseRenderData

type Context

type Context struct {
	Server  *Server
	Session *Session // nil if user isn't logged in

Context is the context used by HTTP handlers.

Use a type assertion to get it from a echo.Context:

ctx := ectx.(*alps.Context)

func (*Context) GetLoginToken

func (ctx *Context) GetLoginToken() (string, string)

func (*Context) SetLoginToken

func (ctx *Context) SetLoginToken(username, password string)

func (*Context) SetSession

func (ctx *Context) SetSession(s *Session)

SetSession sets a cookie for the provided session. Passing a nil session unsets the cookie.

type DialIMAPFunc

type DialIMAPFunc func() (*imapclient.Client, error)

DialIMAPFunc connects to the upstream IMAP server.

type DialSMTPFunc

type DialSMTPFunc func() (*smtp.Client, error)

DialSMTPFunc connects to the upstream SMTP server.

type GlobalRenderData

type GlobalRenderData struct {
	Path []string
	URL  *url.URL

	LoggedIn bool

	// if logged in
	Username string

	Title string

	HavePlugin func(name string) bool

	Notice string

	// additional plugin-specific data
	Extra map[string]interface{}

GlobalRenderData contains data available in all templates.

type GoPlugin

type GoPlugin struct {
	Name string
	// contains filtered or unexported fields

GoPlugin is a helper to create Go plugins.

Use this struct to define your plugin, then call RegisterPluginLoader:

p := GoPlugin{Name: "my-plugin"}
// Define routes, template functions, etc

func (*GoPlugin) AddRoute

func (p *GoPlugin) AddRoute(method, path string, handler HandlerFunc)

AddRoute registers a new HTTP route.

func (*GoPlugin) DELETE

func (p *GoPlugin) DELETE(path string, handler HandlerFunc)

func (*GoPlugin) GET

func (p *GoPlugin) GET(path string, handler HandlerFunc)

func (*GoPlugin) Inject

func (p *GoPlugin) Inject(name string, f InjectFunc)

Inject registers a function to execute prior to rendering a template. The special name "*" matches any template.

func (*GoPlugin) Loader

func (p *GoPlugin) Loader() PluginLoaderFunc

Loader returns a loader function for this plugin.

func (*GoPlugin) POST

func (p *GoPlugin) POST(path string, handler HandlerFunc)

func (*GoPlugin) PUT

func (p *GoPlugin) PUT(path string, handler HandlerFunc)

func (*GoPlugin) Plugin

func (p *GoPlugin) Plugin() Plugin

Plugin returns an object implementing Plugin.

func (*GoPlugin) TemplateFuncs

func (p *GoPlugin) TemplateFuncs(funcs template.FuncMap)

TemplateFuncs registers new template functions.

type HandlerFunc

type HandlerFunc func(*Context) error

HandlerFunc is a function serving HTTP requests.

type InjectFunc

type InjectFunc func(ctx *Context, data RenderData) error

InjectFunc is a function that injects data prior to rendering a template.

type NoUpstreamError

type NoUpstreamError struct {
	// contains filtered or unexported fields

func (*NoUpstreamError) Error

func (err *NoUpstreamError) Error() string

type Options

type Options struct {
	Upstreams  []string
	Theme      string
	ThemesPath string
	Debug      bool
	LoginKey   *fernet.Key

type Plugin

type Plugin interface {
	// Name should return the plugin name.
	Name() string
	// LoadTemplate populates t with the plugin's functions and templates.
	LoadTemplate(t *template.Template) error
	// SetRoutes populates group with the plugin's routes.
	SetRoutes(group *echo.Group)
	// Inject is called prior to rendering a template. It can extend the
	// template data by setting new items in the Extra map.
	Inject(ctx *Context, name string, data RenderData) error
	// Close is called when the plugin is unloaded.
	Close() error

Plugin extends alps with additional functionality.

type PluginLoaderFunc

type PluginLoaderFunc func(*Server) ([]Plugin, error)

PluginLoaderFunc loads plugins for the provided server.

type RenderData

type RenderData interface {
	// GlobalData returns a pointer to the global render data.
	Global() *GlobalRenderData

RenderData is implemented by template data structs. It can be used to inject additional data to all templates.

type Server

type Server struct {
	Sessions *SessionManager
	Options  *Options
	// contains filtered or unexported fields

Server holds all the alps server state.

func New

func New(e *echo.Echo, options *Options) (*Server, error)

New creates a new server.

func (*Server) Close

func (s *Server) Close()

func (*Server) Logger

func (s *Server) Logger() echo.Logger

Logger returns this server's logger.

func (*Server) Reload

func (s *Server) Reload() error

Reload loads Lua plugins and templates from disk.

func (*Server) Upstream

func (s *Server) Upstream(schemes ...string) (*url.URL, error)

Upstream retrieves the configured upstream server URL for the provided schemes. If no configured upstream server matches, a *NoUpstreamError is returned. An empty URL.Scheme means that the caller needs to perform auto-discovery with URL.Host.

type Session

type Session struct {
	// contains filtered or unexported fields

Session is an active user session. It may also hold an IMAP connection.

The session's password is not available to plugins. Plugins should use the session helpers to authenticate outgoing connections, for instance DoSMTP.

func (*Session) Close

func (s *Session) Close()

Close destroys the session. This can be used to log the user out.

func (*Session) DoIMAP

func (s *Session) DoIMAP(f func(*imapclient.Client) error) error

DoIMAP executes an IMAP operation on this session. The IMAP client can only be used from inside f.

func (*Session) DoSMTP

func (s *Session) DoSMTP(f func(*smtp.Client) error) error

DoSMTP executes an SMTP operation on this session. The SMTP client can only be used from inside f.

func (*Session) PopAttachment

func (s *Session) PopAttachment(uuid string) *Attachment

Removes an attachment from the session. Returns nil if there was no such attachment.

func (*Session) PopNotice

func (s *Session) PopNotice() string

func (*Session) PutAttachment

func (s *Session) PutAttachment(in *multipart.FileHeader,
	form *multipart.Form) (string, error)

Puts an attachment and returns a generated UUID

func (*Session) PutNotice

func (s *Session) PutNotice(n string)

func (*Session) SetHTTPBasicAuth

func (s *Session) SetHTTPBasicAuth(req *http.Request)

SetHTTPBasicAuth adds an Authorization header field to the request with this session's credentials.

func (*Session) Store

func (s *Session) Store() Store

Store returns a store suitable for storing persistent user data.

func (*Session) Username

func (s *Session) Username() string

Username returns the session's username.

type SessionManager

type SessionManager struct {
	// contains filtered or unexported fields

SessionManager keeps track of active sessions. It connects and re-connects to the upstream IMAP server as necessary. It prunes expired sessions.

func (*SessionManager) Close

func (sm *SessionManager) Close()

func (*SessionManager) Put

func (sm *SessionManager) Put(username, password string) (*Session, error)

Put connects to the IMAP server and creates a new session. If authentication fails, the error will be of type AuthError.

type Store

type Store interface {
	Get(key string, out interface{}) error
	Put(key string, v interface{}) error

Store allows storing per-user persistent data.

Store shouldn't be used from inside Session.DoIMAP.


Path Synopsis
Package exampleplugin is an example Go plugin for alps.
Package exampleplugin is an example Go plugin for alps.

Jump to

Keyboard shortcuts

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