Documentation ¶
Index ¶
- Variables
- func DecryptObject(key *UserKey, password, ciphertext string, v interface{}) error
- func EncryptObject(key *UserKey, v interface{}) (string, error)
- func GetRandomString(n int) (string, error)
- func RotateMessageKeys(user *User, password string, oldKey, newKey *UserKey, db Datastore) error
- func UpdateKey(key *UserKey, newPassword, oldPassword string) error
- func UpdateUserKey(user *User, newKey *UserKey, password string, db Datastore) error
- type AddDomainParams
- type AddUserParams
- type Address
- type AllMessages
- type ArgonHasher
- type Datastore
- type Domain
- type DomainService
- type DomainStat
- type DomainStore
- type EncryptedMessage
- type FlexibleDomainCheck
- type ForwardingMessage
- type Info
- type Mailbox
- type MailboxParams
- type MailboxService
- func (ms *MailboxService) DeleteExpiredMailboxes(log logger.Logger) error
- func (ms *MailboxService) DeleteMailbox(domain, name string) error
- func (ms *MailboxService) DisableMailboxByExternalID(id string) error
- func (ms *MailboxService) GetMailbox(domain, name string) (*Mailbox, error)
- func (ms *MailboxService) GetOrCreateMailboxForAddress(to string) (*Mailbox, error)
- func (ms *MailboxService) PatchMailbox(domain, name string, params *MailboxParams) error
- func (ms *MailboxService) SetMailbox(domain, name string, userID uint, params *MailboxParams) error
- type MailboxStatStore
- type MailboxStatsService
- type MailboxStore
- type Message
- type MessageService
- type MessageStore
- type StrictDomainCheck
- type User
- type UserIDStore
- type UserKey
- type UserKeyStore
- type UserService
- func (us *UserService) AddInitialAdminUser(params *AddUserParams) error
- func (us *UserService) AddUser(params *AddUserParams) error
- func (us *UserService) CanAddInitialAdminUser() error
- func (us *UserService) GetAllUsersScrubbed() ([]*User, error)
- func (us *UserService) GetUserScrubbed(name string) (*User, error)
- func (us *UserService) UpdateUser(username, oldPassword string, newValue *User) error
- type UserStore
Constants ¶
This section is empty.
Variables ¶
var ( ErrNotFound = errors.New("not found") ErrBackendError = errors.New("couldn't complete database operation") ErrValidationError = errors.New("validation failed") ErrAlreadyExists = errors.New("already exists") ErrInitError = errors.New("could not initialize service") ErrMissingDependency = errors.New("missing dependency") ErrInvalidDestination = errors.New("invalid destination") ErrParsingError = errors.New("parsing error") ErrDomainMisalignment = errors.New("domains not aligned") ErrHashFail = errors.New("error while hashing password") ErrSMTPClientInitFail = errors.New("could not connect to outbound SMTP server") ErrSMTPClientCloseFail = errors.New("could not close connection to outbound SMTP server") ErrSMTPClientSendFail = errors.New("could not send SMTP message") ErrMaxSizeExceeded = errors.New("maximum message size exceeded") ErrMissingID = errors.New("missing ID") ErrPasswordInvalid = errors.New("password invalid") ErrInvalidValue = errors.New("invalid value") ErrCatchAllExists = errors.New("catchall mailbox already exists") )
Functions ¶
func DecryptObject ¶
DecryptObject decrypts an encrypted message using the given key and password, and marshals it into the interface{} provided in v.
func EncryptObject ¶
EncryptObject serializes a given object to JSON, then encrypts the string.
func GetRandomString ¶
GetRandomString returns a random alphanumeric string of length n.
func RotateMessageKeys ¶
RotateMessageKeys rotates the keys used to encrypt all messages owned by a particular user. It attempts to re-encrypt every message it can; however, if there is a message encrypted with an unknown key, it will be left alone.
Types ¶
type AddDomainParams ¶ added in v0.1.12
type AddDomainParams struct { Domain string `json:"domain,omitempty"` CatchallEnabled *bool `json:"catchall_enabled"` }
func (*AddDomainParams) Validate ¶ added in v0.1.12
func (d *AddDomainParams) Validate() error
type AddUserParams ¶ added in v0.1.14
type AddUserParams struct { Username string `json:"username,omitempty"` Email string `json:"email,omitempty"` Password string `json:"password,omitempty"` }
func (*AddUserParams) Validate ¶ added in v0.1.14
func (u *AddUserParams) Validate() error
Validate validates whether the values of the User are valid.
type Address ¶ added in v0.1.2
type Address struct { // A human-readable name for the address Name string // The full email address (e.g. "foo@example.com") Full string // The username portion of the email address (e.g. "foo") Username string // The domain portion of the email address (e.g. "example.com") Domain string }
Address contains information about a parsed email address.
type AllMessages ¶
type AllMessages struct { Messages []Message `json:"messages,omitempty"` EncryptedMessages []EncryptedMessage `json:"encrypted_messages,omitempty"` }
AllMessages is a struct to bind together both encrypted and decrypted messages.
type ArgonHasher ¶ added in v0.1.2
type Datastore ¶
type Datastore interface { DomainStore UserStore UserIDStore UserKeyStore MailboxStore MailboxStatStore MessageStore }
Datastore embeds the datastores for each domain object.
type Domain ¶
type Domain struct { gorm.Model `json:"-"` Domain string `gorm:"type:varchar(255)" json:"domain,omitempty"` CatchallEnabled bool `json:"catchall_enabled"` UserID uint `json:"-"` }
Domain represents an RFC1034 domain name.
type DomainService ¶ added in v0.1.14
type DomainService struct {
// contains filtered or unexported fields
}
func NewDomainService ¶ added in v0.1.14
func NewDomainService(log logger.Logger, db DomainStore) *DomainService
func (*DomainService) AddDomain ¶ added in v0.1.14
func (ds *DomainService) AddDomain(params *AddDomainParams, userID uint) error
func (*DomainService) DeleteDomain ¶ added in v0.1.14
func (ds *DomainService) DeleteDomain(domain string) error
DeleteDomain deletes the domain with the given name.
type DomainStat ¶
type DomainStat struct { gorm.Model `json:"-"` MailboxID uint `json:"-"` Domain string `json:"domain,omitempty"` Count uint `json:"count,omitempty"` }
DomainStat represents a count of unique sources we've seen send mail to this mailbox.
type DomainStore ¶ added in v0.1.13
type DomainStore interface { AddDomain(d *Domain) error GetDomain(name string) (*Domain, error) GetAllDomains() ([]Domain, error) DeleteDomain(d *Domain) error }
DomainStore represents the persistence and retrieval mechanisms for Domain objects.
type EncryptedMessage ¶
type EncryptedMessage struct { gorm.Model `json:"-"` // MailboxID contains the parent mailbox this message is attached to. MailboxID uint `json:"-"` // Content holds an object of type MailMessage after it's been // encrypted. Content string `json:"encrypted_message"` // Fingerprint holds the SHA256 fingerprint of the public key that this // message was encrypted with Fingerprint string `json:"fingerprint"` }
EncryptedMessage represents a Message that has been encrypted using a GPG UserKey.
func EncryptMessage ¶
func EncryptMessage(message *Message, key *UserKey) (*EncryptedMessage, error)
EncryptMessage encrypts an email message under the given key.
type FlexibleDomainCheck ¶ added in v0.1.2
type FlexibleDomainCheck struct{}
FlexibleDomainCheck checks whether the given domains fall within the same effective top-level-domain + 1. Is uses the public suffix list to determine whether the given domains are organizationally equivalent.
func (*FlexibleDomainCheck) ValidateDomainAlignment ¶ added in v0.1.2
func (*FlexibleDomainCheck) ValidateDomainAlignment(a, b string) error
type ForwardingMessage ¶ added in v0.1.2
type ForwardingMessage struct { FromHeader string ToHeader string Subject string TextBody string HTMLBody string }
ForwardingMessage is a stripped-down version of Message that contains only enough information for an SMTP client.
func NewProxyMessage ¶ added in v0.1.2
func NewProxyMessage( message *Message, mailbox *Mailbox, log logger.Logger, userDB UserIDStore, bb *banner.Builder, ) (*ForwardingMessage, error)
NewProxyMessage creates a new message to be sent via an SMTP client. The proxy email sets the "To" header as the mailbox user's configured email. If no forwarding email configuration is found, then both returned items are nil.
type Info ¶
Info contains some metadata about the server. This information is typically baked in at compile time, so in most development cases these fields will be empty.
type Mailbox ¶
type Mailbox struct { gorm.Model `json:"-"` // DomainID is the reference to the domain of this address DomainID uint `json:"-"` // UserID is the reference to the user that owns this mailbox UserID uint `json:"-"` // Name is the name of this mailbox. This is the first part of the associated email address Name string `gorm:"type:varchar(100)" json:"name,omitempty"` // Address holds the full email address of this mailbox Address string `json:"address,omitempty"` // ProxyAddress is the return address used in forwarded emails ProxyAddress string `json:"-"` // Enabled indicates whether this mailbox is enabled or not. If not, then // all mails for this address are rejected similarly to if this mailbox // didn't exist. Enabled bool `json:"enabled"` // Expires indicates an absolute (RFC3339) time for this mailbox to expire. If this is set, // the mailbox will be deleted after the designated time. Expires *time.Time `json:"expires,omitempty"` // DomainWhitelist contains an array of domains to match against. If this is // set, the "from" header for all mail destined for this mailbox must match // one of the domains listed in this whitelist. Whitelist domains may also // be wildcards, with '*' matching multiple characters and '?' matching // single characters. DomainWhitelist pq.StringArray `gorm:"type:varchar(100)[]" json:"domainWhitelist,omitempty"` // ExternalID is a randomly-generated ID which can be used to reference this // mailbox from unauthenticated contexts, such as the "disable mailbox" // endpoint. ExternalID string `json:"-"` }
Mailbox represents all the relevant information about a particular mailbox.
type MailboxParams ¶ added in v0.1.14
type MailboxParams struct { // Enabled indicates whether this mailbox is enabled or not. If not, then // all mail for this address is rejected similarly to if this mailbox // didn't exist. Enabled *bool `json:"enabled,omitempty"` // Expires indicates an absolute (RFC3339) time for this mailbox to expire. If this is set, // the mailbox will be deleted after the designated time. Expires *time.Time `json:"expires,omitempty"` // DomainWhitelist contains an array of domains to match against. If this is // set, the "from" header for all mail destined for this mailbox must match // one of the domains listed in this whitelist. Whitelist domains may also // be wildcards, with '*' matching multiple characters and '?' matching // single characters. DomainWhitelist []string `json:"domainWhitelist,omitempty"` }
func (*MailboxParams) Validate ¶ added in v0.1.14
func (params *MailboxParams) Validate() error
type MailboxService ¶ added in v0.1.14
type MailboxService struct {
// contains filtered or unexported fields
}
func NewMailboxService ¶ added in v0.1.14
func NewMailboxService(db MailboxStore, domains *DomainService) *MailboxService
func (*MailboxService) DeleteExpiredMailboxes ¶ added in v0.1.14
func (ms *MailboxService) DeleteExpiredMailboxes(log logger.Logger) error
DeleteExpiredMailboxes deletes all mailboxes where the current time is past their expiry time.
func (*MailboxService) DeleteMailbox ¶ added in v0.1.14
func (ms *MailboxService) DeleteMailbox(domain, name string) error
DeleteMailbox deletes the mailbox with the given name and domain.
func (*MailboxService) DisableMailboxByExternalID ¶ added in v0.1.14
func (ms *MailboxService) DisableMailboxByExternalID(id string) error
DisableMailboxByExternalID disables a particular mailbox given its external identifier. This may be called from unauthenticated contexts.
func (*MailboxService) GetMailbox ¶ added in v0.1.14
func (ms *MailboxService) GetMailbox(domain, name string) (*Mailbox, error)
GetMailbox gets the mailbox with the given domain and name.
func (*MailboxService) GetOrCreateMailboxForAddress ¶ added in v0.1.14
func (ms *MailboxService) GetOrCreateMailboxForAddress(to string) (*Mailbox, error)
GetOrCreateMailboxForAddress retreives a Mailbox object given an RFC822-formated email address.
func (*MailboxService) PatchMailbox ¶ added in v0.1.14
func (ms *MailboxService) PatchMailbox(domain, name string, params *MailboxParams) error
PatchMailbox updates the values of an existing mailbox.
func (*MailboxService) SetMailbox ¶ added in v0.1.14
func (ms *MailboxService) SetMailbox(domain, name string, userID uint, params *MailboxParams) error
SetMailbox idempotently upserts a mailbox to a specific domain.
type MailboxStatStore ¶ added in v0.1.14
type MailboxStatStore interface { GetStat(mailboxID uint, domain string) (*DomainStat, error) UpdateStat(stat *DomainStat) error CreateStat(stat *DomainStat) error }
MailboxStatStore defines our persistence and retrieval mechaisms for DomainsStat.
type MailboxStatsService ¶ added in v0.1.14
type MailboxStatsService struct {
// contains filtered or unexported fields
}
func NewMailboxStatsService ¶ added in v0.1.14
func NewMailboxStatsService(statsDB MailboxStatStore) *MailboxStatsService
func (*MailboxStatsService) IncrementOrInsertStat ¶ added in v0.1.14
func (mss *MailboxStatsService) IncrementOrInsertStat(mailboxID uint, domain string) error
IncrementOrInsertStat upserts a new statistic to indicate that another email from the given source domain has be received.
type MailboxStore ¶ added in v0.1.13
type MailboxStore interface { GetMailboxByExternalID(id string) (*Mailbox, error) UpdateMailbox(m *Mailbox) error GetMailboxesByDomain(domain *Domain) ([]Mailbox, error) GetMailboxByDomain(domain *Domain, name string) (*Mailbox, error) GetAllMailboxes() ([]Mailbox, error) GetExpiredMailboxes() ([]Mailbox, error) DeleteMailbox(m *Mailbox) error }
MailboxStore defines the persistence and retrieval mechanisms for mailboxes.
type Message ¶
type Message struct { From string `json:"from,omitempty"` To string `json:"to,omitempty"` HTMLBody string `json:"html_body,omitempty"` TextBody string `json:"text_body,omitempty"` Raw string `json:"raw,omitempty"` ReceivedTime time.Time `json:"received_time,omitempty"` FromHeader string `json:"from_header,omitempty"` ToHeader string `json:"to_header,omitempty"` DateHeader time.Time `json:"date_header,omitempty"` Subject string `json:"subject,omitempty"` DKIMStatus string `json:"dkim_status,omitempty"` SPFResult string `json:"spf_result,omitempty"` DKIMAlignment string `json:"dkim_alignment,omitempty"` SPFAlignment string `json:"spf_alignment,omitempty"` }
Message defines all the relevant fields of an email message.
type MessageService ¶ added in v0.1.14
type MessageService struct {
// contains filtered or unexported fields
}
func NewMessageService ¶ added in v0.1.14
func NewMessageService(log logger.Logger, userDB UserIDStore, keyDB UserKeyStore, messageDB MessageStore) *MessageService
func (*MessageService) AddMessage ¶ added in v0.1.14
func (ms *MessageService) AddMessage(message *Message, mailbox *Mailbox) error
func (*MessageService) GetMessages ¶ added in v0.1.14
func (ms *MessageService) GetMessages(mailbox *Mailbox, user *User, password string) (*AllMessages, error)
GetMessages returns all messages for a user and attempts to transparently decrypt them (if they're encrypted with a private key stored in the server).
type MessageStore ¶ added in v0.1.13
type MessageStore interface { AddMessage(mb *Mailbox, m *EncryptedMessage) error GetMessages(mb *Mailbox) ([]EncryptedMessage, error) UpdateMessage(m *EncryptedMessage) error DeleteMessage(m *EncryptedMessage) error GetMessagesForUser(u *User) ([]EncryptedMessage, error) }
MessageStore defines our persistence and retrieval mechaisms for messages.
type StrictDomainCheck ¶ added in v0.1.2
type StrictDomainCheck struct{}
StrictDomainCheck checks whether the domains are exactly equivalent. This is normally less useful, since there are many cases where a sending domain will be slighlly differenct than the domain in the FROM header.
func (*StrictDomainCheck) ValidateDomainAlignment ¶ added in v0.1.2
func (*StrictDomainCheck) ValidateDomainAlignment(a, b string) error
type User ¶
type User struct { gorm.Model `json:"-"` Username string `gorm:"unique_index;type:varchar(100)" json:"username,omitempty"` Email string `gorm:"type:varchar(100)" json:"email,omitempty"` Password string `gorm:"type:varchar(255)" json:"-"` }
User stores information about a user.
type UserIDStore ¶ added in v0.1.14
type UserKey ¶
type UserKey struct { gorm.Model `json:"-"` UserID uint `json:"-"` PrivateKey string `json:"-"` PublicKey string `json:"public_key,omitempty"` }
UserKey defines a GPG key stored in our server. If this contains a private key, it will be used for decryption as well as encryption.
func NewKeyPair ¶
NewKeyPair generates a new PGP key for the given user. The password in the user object MUST be unhashed.
type UserKeyStore ¶ added in v0.1.13
type UserKeyStore interface { AddUserKey(user *User, key *UserKey) error GetUserKey(user *User) (*UserKey, error) UpdateUserKey(key *UserKey) error }
UserKeyStore defines our persistence and retrieval mechanisms for UserKeys.
type UserService ¶ added in v0.1.14
type UserService struct {
// contains filtered or unexported fields
}
func NewUserService ¶ added in v0.1.14
func NewUserService(hasher ArgonHasher, userDB UserStore, keyDB UserKeyStore) *UserService
func (*UserService) AddInitialAdminUser ¶ added in v0.1.14
func (us *UserService) AddInitialAdminUser(params *AddUserParams) error
AddInitialAdminUser checks (1) that there are no other users present, and (2) that the source request is from private IP space. If both are true, the given user is added as the initial admin account.
TODO change this to use the HTTP API instead of interacting direcctly with the database.
func (*UserService) AddUser ¶ added in v0.1.14
func (us *UserService) AddUser(params *AddUserParams) error
AddUser adds a user to the datastore.
func (*UserService) CanAddInitialAdminUser ¶ added in v0.1.14
func (us *UserService) CanAddInitialAdminUser() error
CanAddInitialAdminUser determines whether it's allowed to add the initial admin user. It is only allowed if there are no other users created.
func (*UserService) GetAllUsersScrubbed ¶ added in v0.1.14
func (us *UserService) GetAllUsersScrubbed() ([]*User, error)
func (*UserService) GetUserScrubbed ¶ added in v0.1.14
func (us *UserService) GetUserScrubbed(name string) (*User, error)
func (*UserService) UpdateUser ¶ added in v0.1.14
func (us *UserService) UpdateUser(username, oldPassword string, newValue *User) error
UpdateUser updates a user to the new values given. If the field of newValue is a zero value, it is ignored. If a new password is specified, the user's GPG key is re-encrypted under the new password.