Documentation
¶
Index ¶
- Variables
- func AddInitialAdminUser(db Datastore, user *User) error
- func AddMailbox(domain string, user *User, mailbox *Mailbox, db Datastore) error
- func AddMessage(mailbox *Mailbox, message *Message, key *UserKey, db Datastore) error
- func AddUser(u *User, db Datastore) error
- func CanAddInitialAdminUser(db Datastore) error
- func DecryptObject(key *UserKey, password, ciphertext string, v interface{}) error
- func DeleteDomain(domain string, db Datastore) error
- func DeleteExpiredMailboxes(db Datastore, l *logger.Logger) error
- func DeleteMailbox(domain, name string, db Datastore) error
- func EncryptObject(key *UserKey, v interface{}) (string, error)
- func GetRandomString(n int) (string, error)
- func IncrementOrInsertStat(mailbox *Mailbox, domain string, db Datastore) error
- func RotateMessageKeys(user *User, password string, oldKey, newKey *UserKey, db Datastore) error
- func UpdateKey(key *UserKey, newPassword, oldPassword string) error
- func UpdateMailbox(domain, name string, newValue *Mailbox, db Datastore) error
- func UpdateUser(username, oldPassword string, newValue *User, db Datastore) error
- func UpdateUserKey(user *User, newKey *UserKey, password string, db Datastore) error
- type AllMessages
- type Datastore
- type Domain
- type DomainDatastore
- type DomainStat
- type EncryptedMessage
- type Info
- type Mailbox
- type MailboxDatastore
- type MailboxStatsDatastore
- type Message
- type MessageDatastore
- type User
- type UserDatastore
- type UserKey
- type UserKeyDatastore
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") )
Functions ¶
func AddInitialAdminUser ¶
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.
func AddMailbox ¶
AddMailbox adds a new mailbox to a specific domain, and attaches it to a specific user.
func AddMessage ¶
AddMessage encrypts a message with the given key, then adds it to the given mailbox.
func CanAddInitialAdminUser ¶
CanAddInitialAdminUser determines whether it's allowed to add the initial admin user. It is only allowed if there are no other users created.
func DecryptObject ¶
DecryptObject decrypts an encrypted message using the given key and password, and marshals it into the interface{} provided in v.
func DeleteDomain ¶
DeleteDomain deletes the domain with the given name.
func DeleteExpiredMailboxes ¶
DeleteExpiredMailboxes deletes all mailboxes where the current time is past their expiry time.
func DeleteMailbox ¶
DeleteMailbox deletes the mailbox with the given name and domain.
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 IncrementOrInsertStat ¶
IncrementOrInsertStat upserts a new statistic to indicate that another email from the given source domain has be received.
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.
func UpdateKey ¶
UpdateKey rotates a user key's passphrase (if a private key is stored on the server).
func UpdateMailbox ¶
UpdateMailbox updates the values of an existing mailbox.
func UpdateUser ¶
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.
Types ¶
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.
func GetMessages ¶
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 Datastore ¶
type Datastore interface { DomainDatastore UserDatastore UserKeyDatastore MailboxDatastore MailboxStatsDatastore MessageDatastore }
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"` }
Domain represents an RFC1034 domain name.
type DomainDatastore ¶
type DomainDatastore interface { AddDomain(d *Domain) error GetDomain(name string) (*Domain, error) GetAllDomains() ([]Domain, error) DeleteDomain(d *Domain) error }
DomainDatastore represents the persistence and retrieval mechanisms for Domain objects.
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 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 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"` // IsCatchAll indicates if this is a catch-all mailbox. If it is, all mail // to this mailbox's domain will go to this mailbox if it isn't matched to // another specific mailbox. There can only be one catch-all mailbox per // domain. IsCatchAll bool `json:"isCatchAll,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 pq.StringArray `gorm:"type:varchar(100)[]" json:"domainWhitelist,omitempty"` }
Mailbox represents all the relevant information about a particular mailbox.
func GetMailbox ¶
GetMailbox gets the mailbox with the given domain and name.
type MailboxDatastore ¶
type MailboxDatastore interface { AddMailbox(d *Domain, u *User, m *Mailbox) error GetMailboxesByDomain(domain *Domain) ([]Mailbox, error) GetMailboxByDomain(domain *Domain, name string) (*Mailbox, error) GetAllMailboxes() ([]Mailbox, error) GetExpiredMailboxes() ([]Mailbox, error) UpdateMailbox(m *Mailbox) error GetCatchAll(d *Domain) (*Mailbox, error) DeleteMailbox(m *Mailbox) error }
MailboxDatastore defines the persistence and retrieval mechanisms for mailboxes.
type MailboxStatsDatastore ¶
type MailboxStatsDatastore interface { GetStats(mailbox *Mailbox) ([]DomainStat, error) GetStat(mailbox *Mailbox, domain string) (*DomainStat, error) UpdateStat(stat *DomainStat) error CreateStat(mailbox *Mailbox, stat *DomainStat) error }
MailboxStatsDatastore defines our persistence and retrieval mechaisms for DomainsStat.
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 MessageDatastore ¶
type MessageDatastore 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) }
MessageDatastore defines our persistence and retrieval mechaisms for messages.
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:"password,omitempty"` }
User stores information about a user.
func (*User) HasValidPassword ¶
HasValidPassword checks whether the user has a valid argon2id-formatted password.
func (*User) HashPassword ¶
HashPassword hashes the password under argon2id. TODO turn this into an interface.
type UserDatastore ¶
type UserDatastore interface { AddUser(u *User) error GetUser(name string) (*User, error) UpdateUser(u *User) error GetAllUsers() ([]User, error) GetMailboxUser(mailbox *Mailbox) (*User, error) }
UserDatastore defines all our persistence and retrieval mechanisms for a particular user.
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.