mirror of
https://github.com/mjl-/mox.git
synced 2025-01-14 01:06:27 +03:00
webmail: add server-side stored settings, for signature, top/bottom reply and showing the security indications below address input fields
should solve #102
This commit is contained in:
parent
3bbd7c7d9b
commit
70adf353ee
9 changed files with 409 additions and 27 deletions
|
@ -719,8 +719,44 @@ type LoginSession struct {
|
||||||
csrfToken CSRFToken
|
csrfToken CSRFToken
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Quoting is a setting for how to quote in replies/forwards.
|
||||||
|
type Quoting string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Default Quoting = "" // Bottom-quote if text is selected, top-quote otherwise.
|
||||||
|
Bottom Quoting = "bottom"
|
||||||
|
Top Quoting = "top"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Settings are webmail client settings.
|
||||||
|
type Settings struct {
|
||||||
|
ID uint8 // Singleton ID 1.
|
||||||
|
|
||||||
|
Signature string
|
||||||
|
Quoting Quoting
|
||||||
|
|
||||||
|
// Whether to show the bars underneath the address input fields indicating
|
||||||
|
// starttls/dnssec/dane/mtasts/requiretls support by address.
|
||||||
|
ShowAddressSecurity bool
|
||||||
|
}
|
||||||
|
|
||||||
// Types stored in DB.
|
// Types stored in DB.
|
||||||
var DBTypes = []any{NextUIDValidity{}, Message{}, Recipient{}, Mailbox{}, Subscription{}, Outgoing{}, Password{}, Subjectpass{}, SyncState{}, Upgrade{}, RecipientDomainTLS{}, DiskUsage{}, LoginSession{}}
|
var DBTypes = []any{
|
||||||
|
NextUIDValidity{},
|
||||||
|
Message{},
|
||||||
|
Recipient{},
|
||||||
|
Mailbox{},
|
||||||
|
Subscription{},
|
||||||
|
Outgoing{},
|
||||||
|
Password{},
|
||||||
|
Subjectpass{},
|
||||||
|
SyncState{},
|
||||||
|
Upgrade{},
|
||||||
|
RecipientDomainTLS{},
|
||||||
|
DiskUsage{},
|
||||||
|
LoginSession{},
|
||||||
|
Settings{},
|
||||||
|
}
|
||||||
|
|
||||||
// Account holds the information about a user, includings mailboxes, messages, imap subscriptions.
|
// Account holds the information about a user, includings mailboxes, messages, imap subscriptions.
|
||||||
type Account struct {
|
type Account struct {
|
||||||
|
@ -850,9 +886,15 @@ func OpenAccountDB(log mlog.Log, accountDir, accountName string) (a *Account, re
|
||||||
return acc, nil
|
return acc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure mailbox counts and total message size are set.
|
// Ensure singletons are present. Mailbox counts and total message size, Settings.
|
||||||
var mentioned bool
|
var mentioned bool
|
||||||
err = db.Write(context.TODO(), func(tx *bstore.Tx) error {
|
err = db.Write(context.TODO(), func(tx *bstore.Tx) error {
|
||||||
|
if tx.Get(&Settings{ID: 1}) == bstore.ErrAbsent {
|
||||||
|
if err := tx.Insert(&Settings{ID: 1, ShowAddressSecurity: true}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err := bstore.QueryTx[Mailbox](tx).FilterEqual("HaveCounts", false).ForEach(func(mb Mailbox) error {
|
err := bstore.QueryTx[Mailbox](tx).FilterEqual("HaveCounts", false).ForEach(func(mb Mailbox) error {
|
||||||
if !mentioned {
|
if !mentioned {
|
||||||
mentioned = true
|
mentioned = true
|
||||||
|
@ -886,7 +928,7 @@ func OpenAccountDB(log mlog.Log, accountDir, accountName string) (a *Account, re
|
||||||
return tx.Insert(&du)
|
return tx.Insert(&du)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("calculating counts for mailbox: %v", err)
|
return nil, fmt.Errorf("calculating counts for mailbox or inserting settings: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start adding threading if needed.
|
// Start adding threading if needed.
|
||||||
|
@ -974,6 +1016,9 @@ func initAccount(db *bstore.DB) error {
|
||||||
if err := tx.Insert(&DiskUsage{ID: 1}); err != nil {
|
if err := tx.Insert(&DiskUsage{ID: 1}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := tx.Insert(&Settings{ID: 1}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if len(mox.Conf.Static.DefaultMailboxes) > 0 {
|
if len(mox.Conf.Static.DefaultMailboxes) > 0 {
|
||||||
// Deprecated in favor of InitialMailboxes.
|
// Deprecated in favor of InitialMailboxes.
|
||||||
|
|
|
@ -1536,6 +1536,24 @@ func (Webmail) DecodeMIMEWords(ctx context.Context, text string) string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SettingsSave saves settings, e.g. for composing.
|
||||||
|
func (Webmail) SettingsSave(ctx context.Context, settings store.Settings) {
|
||||||
|
log := pkglog.WithContext(ctx)
|
||||||
|
reqInfo := ctx.Value(requestInfoCtxKey).(requestInfo)
|
||||||
|
acc, err := store.OpenAccount(log, reqInfo.AccountName)
|
||||||
|
xcheckf(ctx, err, "open account")
|
||||||
|
defer func() {
|
||||||
|
if acc != nil {
|
||||||
|
err := acc.Close()
|
||||||
|
log.Check(err, "closing account")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
settings.ID = 1
|
||||||
|
err = acc.DB.Update(ctx, &settings)
|
||||||
|
xcheckf(ctx, err, "save settings")
|
||||||
|
}
|
||||||
|
|
||||||
func slicesAny[T any](l []T) []any {
|
func slicesAny[T any](l []T) []any {
|
||||||
r := make([]any, len(l))
|
r := make([]any, len(l))
|
||||||
for i, v := range l {
|
for i, v := range l {
|
||||||
|
|
|
@ -366,6 +366,19 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Name": "SettingsSave",
|
||||||
|
"Docs": "SettingsSave saves settings, e.g. for composing.",
|
||||||
|
"Params": [
|
||||||
|
{
|
||||||
|
"Name": "settings",
|
||||||
|
"Typewords": [
|
||||||
|
"Settings"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Returns": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Name": "SSETypes",
|
"Name": "SSETypes",
|
||||||
"Docs": "SSETypes exists to ensure the generated API contains the types, for use in SSE events.",
|
"Docs": "SSETypes exists to ensure the generated API contains the types, for use in SSE events.",
|
||||||
|
@ -1382,6 +1395,40 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Name": "Settings",
|
||||||
|
"Docs": "Settings are webmail client settings.",
|
||||||
|
"Fields": [
|
||||||
|
{
|
||||||
|
"Name": "ID",
|
||||||
|
"Docs": "Singleton ID 1.",
|
||||||
|
"Typewords": [
|
||||||
|
"uint8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Signature",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Quoting",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"Quoting"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "ShowAddressSecurity",
|
||||||
|
"Docs": "Whether to show the bars underneath the address input fields indicating starttls/dnssec/dane/mtasts/requiretls support by address.",
|
||||||
|
"Typewords": [
|
||||||
|
"bool"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Name": "EventStart",
|
"Name": "EventStart",
|
||||||
"Docs": "EventStart is the first message sent on an SSE connection, giving the client\nbasic data to populate its UI. After this event, messages will follow quickly in\nan EventViewMsgs event.",
|
"Docs": "EventStart is the first message sent on an SSE connection, giving the client\nbasic data to populate its UI. After this event, messages will follow quickly in\nan EventViewMsgs event.",
|
||||||
|
@ -1438,6 +1485,13 @@
|
||||||
"string"
|
"string"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Name": "Settings",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"Settings"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Name": "Version",
|
"Name": "Version",
|
||||||
"Docs": "",
|
"Docs": "",
|
||||||
|
@ -2815,6 +2869,27 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Name": "Quoting",
|
||||||
|
"Docs": "Quoting is a setting for how to quote in replies/forwards.",
|
||||||
|
"Values": [
|
||||||
|
{
|
||||||
|
"Name": "Default",
|
||||||
|
"Value": "",
|
||||||
|
"Docs": "Bottom-quote if text is selected, top-quote otherwise."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Bottom",
|
||||||
|
"Value": "bottom",
|
||||||
|
"Docs": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Top",
|
||||||
|
"Value": "top",
|
||||||
|
"Docs": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Name": "Localpart",
|
"Name": "Localpart",
|
||||||
"Docs": "Localpart is a decoded local part of an email address, before the \"@\".\nFor quoted strings, values do not hold the double quote or escaping backslashes.\nAn empty string can be a valid localpart.\nLocalparts are in Unicode NFC.",
|
"Docs": "Localpart is a decoded local part of an email address, before the \"@\".\nFor quoted strings, values do not hold the double quote or escaping backslashes.\nAn empty string can be a valid localpart.\nLocalparts are in Unicode NFC.",
|
||||||
|
|
|
@ -190,6 +190,14 @@ export interface RecipientSecurity {
|
||||||
RequireTLS: SecurityResult // Whether recipient domain is known to implement the REQUIRETLS SMTP extension. Will be "unknown" if no delivery to the domain has been attempted yet.
|
RequireTLS: SecurityResult // Whether recipient domain is known to implement the REQUIRETLS SMTP extension. Will be "unknown" if no delivery to the domain has been attempted yet.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Settings are webmail client settings.
|
||||||
|
export interface Settings {
|
||||||
|
ID: number // Singleton ID 1.
|
||||||
|
Signature: string
|
||||||
|
Quoting: Quoting
|
||||||
|
ShowAddressSecurity: boolean // Whether to show the bars underneath the address input fields indicating starttls/dnssec/dane/mtasts/requiretls support by address.
|
||||||
|
}
|
||||||
|
|
||||||
// EventStart is the first message sent on an SSE connection, giving the client
|
// EventStart is the first message sent on an SSE connection, giving the client
|
||||||
// basic data to populate its UI. After this event, messages will follow quickly in
|
// basic data to populate its UI. After this event, messages will follow quickly in
|
||||||
// an EventViewMsgs event.
|
// an EventViewMsgs event.
|
||||||
|
@ -201,6 +209,7 @@ export interface EventStart {
|
||||||
MailboxName: string
|
MailboxName: string
|
||||||
Mailboxes?: Mailbox[] | null
|
Mailboxes?: Mailbox[] | null
|
||||||
RejectsMailbox: string
|
RejectsMailbox: string
|
||||||
|
Settings: Settings
|
||||||
Version: string
|
Version: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,14 +522,21 @@ export enum SecurityResult {
|
||||||
SecurityResultUnknown = "unknown",
|
SecurityResultUnknown = "unknown",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Quoting is a setting for how to quote in replies/forwards.
|
||||||
|
export enum Quoting {
|
||||||
|
Default = "", // Bottom-quote if text is selected, top-quote otherwise.
|
||||||
|
Bottom = "bottom",
|
||||||
|
Top = "top",
|
||||||
|
}
|
||||||
|
|
||||||
// Localpart is a decoded local part of an email address, before the "@".
|
// Localpart is a decoded local part of an email address, before the "@".
|
||||||
// For quoted strings, values do not hold the double quote or escaping backslashes.
|
// For quoted strings, values do not hold the double quote or escaping backslashes.
|
||||||
// An empty string can be a valid localpart.
|
// An empty string can be a valid localpart.
|
||||||
// Localparts are in Unicode NFC.
|
// Localparts are in Unicode NFC.
|
||||||
export type Localpart = string
|
export type Localpart = string
|
||||||
|
|
||||||
export const structTypes: {[typename: string]: boolean} = {"Address":true,"Attachment":true,"ChangeMailboxAdd":true,"ChangeMailboxCounts":true,"ChangeMailboxKeywords":true,"ChangeMailboxRemove":true,"ChangeMailboxRename":true,"ChangeMailboxSpecialUse":true,"ChangeMsgAdd":true,"ChangeMsgFlags":true,"ChangeMsgRemove":true,"ChangeMsgThread":true,"Domain":true,"DomainAddressConfig":true,"Envelope":true,"EventStart":true,"EventViewChanges":true,"EventViewErr":true,"EventViewMsgs":true,"EventViewReset":true,"File":true,"Filter":true,"Flags":true,"ForwardAttachments":true,"Mailbox":true,"Message":true,"MessageAddress":true,"MessageEnvelope":true,"MessageItem":true,"NotFilter":true,"Page":true,"ParsedMessage":true,"Part":true,"Query":true,"RecipientSecurity":true,"Request":true,"SpecialUse":true,"SubmitMessage":true}
|
export const structTypes: {[typename: string]: boolean} = {"Address":true,"Attachment":true,"ChangeMailboxAdd":true,"ChangeMailboxCounts":true,"ChangeMailboxKeywords":true,"ChangeMailboxRemove":true,"ChangeMailboxRename":true,"ChangeMailboxSpecialUse":true,"ChangeMsgAdd":true,"ChangeMsgFlags":true,"ChangeMsgRemove":true,"ChangeMsgThread":true,"Domain":true,"DomainAddressConfig":true,"Envelope":true,"EventStart":true,"EventViewChanges":true,"EventViewErr":true,"EventViewMsgs":true,"EventViewReset":true,"File":true,"Filter":true,"Flags":true,"ForwardAttachments":true,"Mailbox":true,"Message":true,"MessageAddress":true,"MessageEnvelope":true,"MessageItem":true,"NotFilter":true,"Page":true,"ParsedMessage":true,"Part":true,"Query":true,"RecipientSecurity":true,"Request":true,"Settings":true,"SpecialUse":true,"SubmitMessage":true}
|
||||||
export const stringsTypes: {[typename: string]: boolean} = {"AttachmentType":true,"CSRFToken":true,"Localpart":true,"SecurityResult":true,"ThreadMode":true}
|
export const stringsTypes: {[typename: string]: boolean} = {"AttachmentType":true,"CSRFToken":true,"Localpart":true,"Quoting":true,"SecurityResult":true,"ThreadMode":true}
|
||||||
export const intsTypes: {[typename: string]: boolean} = {"ModSeq":true,"UID":true,"Validation":true}
|
export const intsTypes: {[typename: string]: boolean} = {"ModSeq":true,"UID":true,"Validation":true}
|
||||||
export const types: TypenameMap = {
|
export const types: TypenameMap = {
|
||||||
"Request": {"Name":"Request","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"SSEID","Docs":"","Typewords":["int64"]},{"Name":"ViewID","Docs":"","Typewords":["int64"]},{"Name":"Cancel","Docs":"","Typewords":["bool"]},{"Name":"Query","Docs":"","Typewords":["Query"]},{"Name":"Page","Docs":"","Typewords":["Page"]}]},
|
"Request": {"Name":"Request","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"SSEID","Docs":"","Typewords":["int64"]},{"Name":"ViewID","Docs":"","Typewords":["int64"]},{"Name":"Cancel","Docs":"","Typewords":["bool"]},{"Name":"Query","Docs":"","Typewords":["Query"]},{"Name":"Page","Docs":"","Typewords":["Page"]}]},
|
||||||
|
@ -539,7 +555,8 @@ export const types: TypenameMap = {
|
||||||
"ForwardAttachments": {"Name":"ForwardAttachments","Docs":"","Fields":[{"Name":"MessageID","Docs":"","Typewords":["int64"]},{"Name":"Paths","Docs":"","Typewords":["[]","[]","int32"]}]},
|
"ForwardAttachments": {"Name":"ForwardAttachments","Docs":"","Fields":[{"Name":"MessageID","Docs":"","Typewords":["int64"]},{"Name":"Paths","Docs":"","Typewords":["[]","[]","int32"]}]},
|
||||||
"Mailbox": {"Name":"Mailbox","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"Name","Docs":"","Typewords":["string"]},{"Name":"UIDValidity","Docs":"","Typewords":["uint32"]},{"Name":"UIDNext","Docs":"","Typewords":["UID"]},{"Name":"Archive","Docs":"","Typewords":["bool"]},{"Name":"Draft","Docs":"","Typewords":["bool"]},{"Name":"Junk","Docs":"","Typewords":["bool"]},{"Name":"Sent","Docs":"","Typewords":["bool"]},{"Name":"Trash","Docs":"","Typewords":["bool"]},{"Name":"Keywords","Docs":"","Typewords":["[]","string"]},{"Name":"HaveCounts","Docs":"","Typewords":["bool"]},{"Name":"Total","Docs":"","Typewords":["int64"]},{"Name":"Deleted","Docs":"","Typewords":["int64"]},{"Name":"Unread","Docs":"","Typewords":["int64"]},{"Name":"Unseen","Docs":"","Typewords":["int64"]},{"Name":"Size","Docs":"","Typewords":["int64"]}]},
|
"Mailbox": {"Name":"Mailbox","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"Name","Docs":"","Typewords":["string"]},{"Name":"UIDValidity","Docs":"","Typewords":["uint32"]},{"Name":"UIDNext","Docs":"","Typewords":["UID"]},{"Name":"Archive","Docs":"","Typewords":["bool"]},{"Name":"Draft","Docs":"","Typewords":["bool"]},{"Name":"Junk","Docs":"","Typewords":["bool"]},{"Name":"Sent","Docs":"","Typewords":["bool"]},{"Name":"Trash","Docs":"","Typewords":["bool"]},{"Name":"Keywords","Docs":"","Typewords":["[]","string"]},{"Name":"HaveCounts","Docs":"","Typewords":["bool"]},{"Name":"Total","Docs":"","Typewords":["int64"]},{"Name":"Deleted","Docs":"","Typewords":["int64"]},{"Name":"Unread","Docs":"","Typewords":["int64"]},{"Name":"Unseen","Docs":"","Typewords":["int64"]},{"Name":"Size","Docs":"","Typewords":["int64"]}]},
|
||||||
"RecipientSecurity": {"Name":"RecipientSecurity","Docs":"","Fields":[{"Name":"STARTTLS","Docs":"","Typewords":["SecurityResult"]},{"Name":"MTASTS","Docs":"","Typewords":["SecurityResult"]},{"Name":"DNSSEC","Docs":"","Typewords":["SecurityResult"]},{"Name":"DANE","Docs":"","Typewords":["SecurityResult"]},{"Name":"RequireTLS","Docs":"","Typewords":["SecurityResult"]}]},
|
"RecipientSecurity": {"Name":"RecipientSecurity","Docs":"","Fields":[{"Name":"STARTTLS","Docs":"","Typewords":["SecurityResult"]},{"Name":"MTASTS","Docs":"","Typewords":["SecurityResult"]},{"Name":"DNSSEC","Docs":"","Typewords":["SecurityResult"]},{"Name":"DANE","Docs":"","Typewords":["SecurityResult"]},{"Name":"RequireTLS","Docs":"","Typewords":["SecurityResult"]}]},
|
||||||
"EventStart": {"Name":"EventStart","Docs":"","Fields":[{"Name":"SSEID","Docs":"","Typewords":["int64"]},{"Name":"LoginAddress","Docs":"","Typewords":["MessageAddress"]},{"Name":"Addresses","Docs":"","Typewords":["[]","MessageAddress"]},{"Name":"DomainAddressConfigs","Docs":"","Typewords":["{}","DomainAddressConfig"]},{"Name":"MailboxName","Docs":"","Typewords":["string"]},{"Name":"Mailboxes","Docs":"","Typewords":["[]","Mailbox"]},{"Name":"RejectsMailbox","Docs":"","Typewords":["string"]},{"Name":"Version","Docs":"","Typewords":["string"]}]},
|
"Settings": {"Name":"Settings","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["uint8"]},{"Name":"Signature","Docs":"","Typewords":["string"]},{"Name":"Quoting","Docs":"","Typewords":["Quoting"]},{"Name":"ShowAddressSecurity","Docs":"","Typewords":["bool"]}]},
|
||||||
|
"EventStart": {"Name":"EventStart","Docs":"","Fields":[{"Name":"SSEID","Docs":"","Typewords":["int64"]},{"Name":"LoginAddress","Docs":"","Typewords":["MessageAddress"]},{"Name":"Addresses","Docs":"","Typewords":["[]","MessageAddress"]},{"Name":"DomainAddressConfigs","Docs":"","Typewords":["{}","DomainAddressConfig"]},{"Name":"MailboxName","Docs":"","Typewords":["string"]},{"Name":"Mailboxes","Docs":"","Typewords":["[]","Mailbox"]},{"Name":"RejectsMailbox","Docs":"","Typewords":["string"]},{"Name":"Settings","Docs":"","Typewords":["Settings"]},{"Name":"Version","Docs":"","Typewords":["string"]}]},
|
||||||
"DomainAddressConfig": {"Name":"DomainAddressConfig","Docs":"","Fields":[{"Name":"LocalpartCatchallSeparator","Docs":"","Typewords":["string"]},{"Name":"LocalpartCaseSensitive","Docs":"","Typewords":["bool"]}]},
|
"DomainAddressConfig": {"Name":"DomainAddressConfig","Docs":"","Fields":[{"Name":"LocalpartCatchallSeparator","Docs":"","Typewords":["string"]},{"Name":"LocalpartCaseSensitive","Docs":"","Typewords":["bool"]}]},
|
||||||
"EventViewErr": {"Name":"EventViewErr","Docs":"","Fields":[{"Name":"ViewID","Docs":"","Typewords":["int64"]},{"Name":"RequestID","Docs":"","Typewords":["int64"]},{"Name":"Err","Docs":"","Typewords":["string"]}]},
|
"EventViewErr": {"Name":"EventViewErr","Docs":"","Fields":[{"Name":"ViewID","Docs":"","Typewords":["int64"]},{"Name":"RequestID","Docs":"","Typewords":["int64"]},{"Name":"Err","Docs":"","Typewords":["string"]}]},
|
||||||
"EventViewReset": {"Name":"EventViewReset","Docs":"","Fields":[{"Name":"ViewID","Docs":"","Typewords":["int64"]},{"Name":"RequestID","Docs":"","Typewords":["int64"]}]},
|
"EventViewReset": {"Name":"EventViewReset","Docs":"","Fields":[{"Name":"ViewID","Docs":"","Typewords":["int64"]},{"Name":"RequestID","Docs":"","Typewords":["int64"]}]},
|
||||||
|
@ -568,6 +585,7 @@ export const types: TypenameMap = {
|
||||||
"ThreadMode": {"Name":"ThreadMode","Docs":"","Values":[{"Name":"ThreadOff","Value":"off","Docs":""},{"Name":"ThreadOn","Value":"on","Docs":""},{"Name":"ThreadUnread","Value":"unread","Docs":""}]},
|
"ThreadMode": {"Name":"ThreadMode","Docs":"","Values":[{"Name":"ThreadOff","Value":"off","Docs":""},{"Name":"ThreadOn","Value":"on","Docs":""},{"Name":"ThreadUnread","Value":"unread","Docs":""}]},
|
||||||
"AttachmentType": {"Name":"AttachmentType","Docs":"","Values":[{"Name":"AttachmentIndifferent","Value":"","Docs":""},{"Name":"AttachmentNone","Value":"none","Docs":""},{"Name":"AttachmentAny","Value":"any","Docs":""},{"Name":"AttachmentImage","Value":"image","Docs":""},{"Name":"AttachmentPDF","Value":"pdf","Docs":""},{"Name":"AttachmentArchive","Value":"archive","Docs":""},{"Name":"AttachmentSpreadsheet","Value":"spreadsheet","Docs":""},{"Name":"AttachmentDocument","Value":"document","Docs":""},{"Name":"AttachmentPresentation","Value":"presentation","Docs":""}]},
|
"AttachmentType": {"Name":"AttachmentType","Docs":"","Values":[{"Name":"AttachmentIndifferent","Value":"","Docs":""},{"Name":"AttachmentNone","Value":"none","Docs":""},{"Name":"AttachmentAny","Value":"any","Docs":""},{"Name":"AttachmentImage","Value":"image","Docs":""},{"Name":"AttachmentPDF","Value":"pdf","Docs":""},{"Name":"AttachmentArchive","Value":"archive","Docs":""},{"Name":"AttachmentSpreadsheet","Value":"spreadsheet","Docs":""},{"Name":"AttachmentDocument","Value":"document","Docs":""},{"Name":"AttachmentPresentation","Value":"presentation","Docs":""}]},
|
||||||
"SecurityResult": {"Name":"SecurityResult","Docs":"","Values":[{"Name":"SecurityResultError","Value":"error","Docs":""},{"Name":"SecurityResultNo","Value":"no","Docs":""},{"Name":"SecurityResultYes","Value":"yes","Docs":""},{"Name":"SecurityResultUnknown","Value":"unknown","Docs":""}]},
|
"SecurityResult": {"Name":"SecurityResult","Docs":"","Values":[{"Name":"SecurityResultError","Value":"error","Docs":""},{"Name":"SecurityResultNo","Value":"no","Docs":""},{"Name":"SecurityResultYes","Value":"yes","Docs":""},{"Name":"SecurityResultUnknown","Value":"unknown","Docs":""}]},
|
||||||
|
"Quoting": {"Name":"Quoting","Docs":"","Values":[{"Name":"Default","Value":"","Docs":""},{"Name":"Bottom","Value":"bottom","Docs":""},{"Name":"Top","Value":"top","Docs":""}]},
|
||||||
"Localpart": {"Name":"Localpart","Docs":"","Values":null},
|
"Localpart": {"Name":"Localpart","Docs":"","Values":null},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,6 +606,7 @@ export const parser = {
|
||||||
ForwardAttachments: (v: any) => parse("ForwardAttachments", v) as ForwardAttachments,
|
ForwardAttachments: (v: any) => parse("ForwardAttachments", v) as ForwardAttachments,
|
||||||
Mailbox: (v: any) => parse("Mailbox", v) as Mailbox,
|
Mailbox: (v: any) => parse("Mailbox", v) as Mailbox,
|
||||||
RecipientSecurity: (v: any) => parse("RecipientSecurity", v) as RecipientSecurity,
|
RecipientSecurity: (v: any) => parse("RecipientSecurity", v) as RecipientSecurity,
|
||||||
|
Settings: (v: any) => parse("Settings", v) as Settings,
|
||||||
EventStart: (v: any) => parse("EventStart", v) as EventStart,
|
EventStart: (v: any) => parse("EventStart", v) as EventStart,
|
||||||
DomainAddressConfig: (v: any) => parse("DomainAddressConfig", v) as DomainAddressConfig,
|
DomainAddressConfig: (v: any) => parse("DomainAddressConfig", v) as DomainAddressConfig,
|
||||||
EventViewErr: (v: any) => parse("EventViewErr", v) as EventViewErr,
|
EventViewErr: (v: any) => parse("EventViewErr", v) as EventViewErr,
|
||||||
|
@ -617,6 +636,7 @@ export const parser = {
|
||||||
ThreadMode: (v: any) => parse("ThreadMode", v) as ThreadMode,
|
ThreadMode: (v: any) => parse("ThreadMode", v) as ThreadMode,
|
||||||
AttachmentType: (v: any) => parse("AttachmentType", v) as AttachmentType,
|
AttachmentType: (v: any) => parse("AttachmentType", v) as AttachmentType,
|
||||||
SecurityResult: (v: any) => parse("SecurityResult", v) as SecurityResult,
|
SecurityResult: (v: any) => parse("SecurityResult", v) as SecurityResult,
|
||||||
|
Quoting: (v: any) => parse("Quoting", v) as Quoting,
|
||||||
Localpart: (v: any) => parse("Localpart", v) as Localpart,
|
Localpart: (v: any) => parse("Localpart", v) as Localpart,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,6 +881,15 @@ export class Client {
|
||||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as string
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SettingsSave saves settings, e.g. for composing.
|
||||||
|
async SettingsSave(settings: Settings): Promise<void> {
|
||||||
|
const fn: string = "SettingsSave"
|
||||||
|
const paramTypes: string[][] = [["Settings"]]
|
||||||
|
const returnTypes: string[][] = []
|
||||||
|
const params: any[] = [settings]
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as void
|
||||||
|
}
|
||||||
|
|
||||||
// SSETypes exists to ensure the generated API contains the types, for use in SSE events.
|
// SSETypes exists to ensure the generated API contains the types, for use in SSE events.
|
||||||
async SSETypes(): Promise<[EventStart, EventViewErr, EventViewReset, EventViewMsgs, EventViewChanges, ChangeMsgAdd, ChangeMsgRemove, ChangeMsgFlags, ChangeMsgThread, ChangeMailboxRemove, ChangeMailboxAdd, ChangeMailboxRename, ChangeMailboxCounts, ChangeMailboxSpecialUse, ChangeMailboxKeywords, Flags]> {
|
async SSETypes(): Promise<[EventStart, EventViewErr, EventViewReset, EventViewMsgs, EventViewChanges, ChangeMsgAdd, ChangeMsgRemove, ChangeMsgFlags, ChangeMsgThread, ChangeMailboxRemove, ChangeMailboxAdd, ChangeMailboxRename, ChangeMailboxCounts, ChangeMailboxSpecialUse, ChangeMailboxKeywords, Flags]> {
|
||||||
const fn: string = "SSETypes"
|
const fn: string = "SSETypes"
|
||||||
|
|
|
@ -274,8 +274,15 @@ var api;
|
||||||
// lookups.
|
// lookups.
|
||||||
SecurityResult["SecurityResultUnknown"] = "unknown";
|
SecurityResult["SecurityResultUnknown"] = "unknown";
|
||||||
})(SecurityResult = api.SecurityResult || (api.SecurityResult = {}));
|
})(SecurityResult = api.SecurityResult || (api.SecurityResult = {}));
|
||||||
api.structTypes = { "Address": true, "Attachment": true, "ChangeMailboxAdd": true, "ChangeMailboxCounts": true, "ChangeMailboxKeywords": true, "ChangeMailboxRemove": true, "ChangeMailboxRename": true, "ChangeMailboxSpecialUse": true, "ChangeMsgAdd": true, "ChangeMsgFlags": true, "ChangeMsgRemove": true, "ChangeMsgThread": true, "Domain": true, "DomainAddressConfig": true, "Envelope": true, "EventStart": true, "EventViewChanges": true, "EventViewErr": true, "EventViewMsgs": true, "EventViewReset": true, "File": true, "Filter": true, "Flags": true, "ForwardAttachments": true, "Mailbox": true, "Message": true, "MessageAddress": true, "MessageEnvelope": true, "MessageItem": true, "NotFilter": true, "Page": true, "ParsedMessage": true, "Part": true, "Query": true, "RecipientSecurity": true, "Request": true, "SpecialUse": true, "SubmitMessage": true };
|
// Quoting is a setting for how to quote in replies/forwards.
|
||||||
api.stringsTypes = { "AttachmentType": true, "CSRFToken": true, "Localpart": true, "SecurityResult": true, "ThreadMode": true };
|
let Quoting;
|
||||||
|
(function (Quoting) {
|
||||||
|
Quoting["Default"] = "";
|
||||||
|
Quoting["Bottom"] = "bottom";
|
||||||
|
Quoting["Top"] = "top";
|
||||||
|
})(Quoting = api.Quoting || (api.Quoting = {}));
|
||||||
|
api.structTypes = { "Address": true, "Attachment": true, "ChangeMailboxAdd": true, "ChangeMailboxCounts": true, "ChangeMailboxKeywords": true, "ChangeMailboxRemove": true, "ChangeMailboxRename": true, "ChangeMailboxSpecialUse": true, "ChangeMsgAdd": true, "ChangeMsgFlags": true, "ChangeMsgRemove": true, "ChangeMsgThread": true, "Domain": true, "DomainAddressConfig": true, "Envelope": true, "EventStart": true, "EventViewChanges": true, "EventViewErr": true, "EventViewMsgs": true, "EventViewReset": true, "File": true, "Filter": true, "Flags": true, "ForwardAttachments": true, "Mailbox": true, "Message": true, "MessageAddress": true, "MessageEnvelope": true, "MessageItem": true, "NotFilter": true, "Page": true, "ParsedMessage": true, "Part": true, "Query": true, "RecipientSecurity": true, "Request": true, "Settings": true, "SpecialUse": true, "SubmitMessage": true };
|
||||||
|
api.stringsTypes = { "AttachmentType": true, "CSRFToken": true, "Localpart": true, "Quoting": true, "SecurityResult": true, "ThreadMode": true };
|
||||||
api.intsTypes = { "ModSeq": true, "UID": true, "Validation": true };
|
api.intsTypes = { "ModSeq": true, "UID": true, "Validation": true };
|
||||||
api.types = {
|
api.types = {
|
||||||
"Request": { "Name": "Request", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Cancel", "Docs": "", "Typewords": ["bool"] }, { "Name": "Query", "Docs": "", "Typewords": ["Query"] }, { "Name": "Page", "Docs": "", "Typewords": ["Page"] }] },
|
"Request": { "Name": "Request", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Cancel", "Docs": "", "Typewords": ["bool"] }, { "Name": "Query", "Docs": "", "Typewords": ["Query"] }, { "Name": "Page", "Docs": "", "Typewords": ["Page"] }] },
|
||||||
|
@ -294,7 +301,8 @@ var api;
|
||||||
"ForwardAttachments": { "Name": "ForwardAttachments", "Docs": "", "Fields": [{ "Name": "MessageID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Paths", "Docs": "", "Typewords": ["[]", "[]", "int32"] }] },
|
"ForwardAttachments": { "Name": "ForwardAttachments", "Docs": "", "Fields": [{ "Name": "MessageID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Paths", "Docs": "", "Typewords": ["[]", "[]", "int32"] }] },
|
||||||
"Mailbox": { "Name": "Mailbox", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "UIDValidity", "Docs": "", "Typewords": ["uint32"] }, { "Name": "UIDNext", "Docs": "", "Typewords": ["UID"] }, { "Name": "Archive", "Docs": "", "Typewords": ["bool"] }, { "Name": "Draft", "Docs": "", "Typewords": ["bool"] }, { "Name": "Junk", "Docs": "", "Typewords": ["bool"] }, { "Name": "Sent", "Docs": "", "Typewords": ["bool"] }, { "Name": "Trash", "Docs": "", "Typewords": ["bool"] }, { "Name": "Keywords", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "HaveCounts", "Docs": "", "Typewords": ["bool"] }, { "Name": "Total", "Docs": "", "Typewords": ["int64"] }, { "Name": "Deleted", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unread", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unseen", "Docs": "", "Typewords": ["int64"] }, { "Name": "Size", "Docs": "", "Typewords": ["int64"] }] },
|
"Mailbox": { "Name": "Mailbox", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "UIDValidity", "Docs": "", "Typewords": ["uint32"] }, { "Name": "UIDNext", "Docs": "", "Typewords": ["UID"] }, { "Name": "Archive", "Docs": "", "Typewords": ["bool"] }, { "Name": "Draft", "Docs": "", "Typewords": ["bool"] }, { "Name": "Junk", "Docs": "", "Typewords": ["bool"] }, { "Name": "Sent", "Docs": "", "Typewords": ["bool"] }, { "Name": "Trash", "Docs": "", "Typewords": ["bool"] }, { "Name": "Keywords", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "HaveCounts", "Docs": "", "Typewords": ["bool"] }, { "Name": "Total", "Docs": "", "Typewords": ["int64"] }, { "Name": "Deleted", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unread", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unseen", "Docs": "", "Typewords": ["int64"] }, { "Name": "Size", "Docs": "", "Typewords": ["int64"] }] },
|
||||||
"RecipientSecurity": { "Name": "RecipientSecurity", "Docs": "", "Fields": [{ "Name": "STARTTLS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "MTASTS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DNSSEC", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DANE", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "RequireTLS", "Docs": "", "Typewords": ["SecurityResult"] }] },
|
"RecipientSecurity": { "Name": "RecipientSecurity", "Docs": "", "Fields": [{ "Name": "STARTTLS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "MTASTS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DNSSEC", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DANE", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "RequireTLS", "Docs": "", "Typewords": ["SecurityResult"] }] },
|
||||||
"EventStart": { "Name": "EventStart", "Docs": "", "Fields": [{ "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "LoginAddress", "Docs": "", "Typewords": ["MessageAddress"] }, { "Name": "Addresses", "Docs": "", "Typewords": ["[]", "MessageAddress"] }, { "Name": "DomainAddressConfigs", "Docs": "", "Typewords": ["{}", "DomainAddressConfig"] }, { "Name": "MailboxName", "Docs": "", "Typewords": ["string"] }, { "Name": "Mailboxes", "Docs": "", "Typewords": ["[]", "Mailbox"] }, { "Name": "RejectsMailbox", "Docs": "", "Typewords": ["string"] }, { "Name": "Version", "Docs": "", "Typewords": ["string"] }] },
|
"Settings": { "Name": "Settings", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["uint8"] }, { "Name": "Signature", "Docs": "", "Typewords": ["string"] }, { "Name": "Quoting", "Docs": "", "Typewords": ["Quoting"] }, { "Name": "ShowAddressSecurity", "Docs": "", "Typewords": ["bool"] }] },
|
||||||
|
"EventStart": { "Name": "EventStart", "Docs": "", "Fields": [{ "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "LoginAddress", "Docs": "", "Typewords": ["MessageAddress"] }, { "Name": "Addresses", "Docs": "", "Typewords": ["[]", "MessageAddress"] }, { "Name": "DomainAddressConfigs", "Docs": "", "Typewords": ["{}", "DomainAddressConfig"] }, { "Name": "MailboxName", "Docs": "", "Typewords": ["string"] }, { "Name": "Mailboxes", "Docs": "", "Typewords": ["[]", "Mailbox"] }, { "Name": "RejectsMailbox", "Docs": "", "Typewords": ["string"] }, { "Name": "Settings", "Docs": "", "Typewords": ["Settings"] }, { "Name": "Version", "Docs": "", "Typewords": ["string"] }] },
|
||||||
"DomainAddressConfig": { "Name": "DomainAddressConfig", "Docs": "", "Fields": [{ "Name": "LocalpartCatchallSeparator", "Docs": "", "Typewords": ["string"] }, { "Name": "LocalpartCaseSensitive", "Docs": "", "Typewords": ["bool"] }] },
|
"DomainAddressConfig": { "Name": "DomainAddressConfig", "Docs": "", "Fields": [{ "Name": "LocalpartCatchallSeparator", "Docs": "", "Typewords": ["string"] }, { "Name": "LocalpartCaseSensitive", "Docs": "", "Typewords": ["bool"] }] },
|
||||||
"EventViewErr": { "Name": "EventViewErr", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Err", "Docs": "", "Typewords": ["string"] }] },
|
"EventViewErr": { "Name": "EventViewErr", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Err", "Docs": "", "Typewords": ["string"] }] },
|
||||||
"EventViewReset": { "Name": "EventViewReset", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }] },
|
"EventViewReset": { "Name": "EventViewReset", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }] },
|
||||||
|
@ -323,6 +331,7 @@ var api;
|
||||||
"ThreadMode": { "Name": "ThreadMode", "Docs": "", "Values": [{ "Name": "ThreadOff", "Value": "off", "Docs": "" }, { "Name": "ThreadOn", "Value": "on", "Docs": "" }, { "Name": "ThreadUnread", "Value": "unread", "Docs": "" }] },
|
"ThreadMode": { "Name": "ThreadMode", "Docs": "", "Values": [{ "Name": "ThreadOff", "Value": "off", "Docs": "" }, { "Name": "ThreadOn", "Value": "on", "Docs": "" }, { "Name": "ThreadUnread", "Value": "unread", "Docs": "" }] },
|
||||||
"AttachmentType": { "Name": "AttachmentType", "Docs": "", "Values": [{ "Name": "AttachmentIndifferent", "Value": "", "Docs": "" }, { "Name": "AttachmentNone", "Value": "none", "Docs": "" }, { "Name": "AttachmentAny", "Value": "any", "Docs": "" }, { "Name": "AttachmentImage", "Value": "image", "Docs": "" }, { "Name": "AttachmentPDF", "Value": "pdf", "Docs": "" }, { "Name": "AttachmentArchive", "Value": "archive", "Docs": "" }, { "Name": "AttachmentSpreadsheet", "Value": "spreadsheet", "Docs": "" }, { "Name": "AttachmentDocument", "Value": "document", "Docs": "" }, { "Name": "AttachmentPresentation", "Value": "presentation", "Docs": "" }] },
|
"AttachmentType": { "Name": "AttachmentType", "Docs": "", "Values": [{ "Name": "AttachmentIndifferent", "Value": "", "Docs": "" }, { "Name": "AttachmentNone", "Value": "none", "Docs": "" }, { "Name": "AttachmentAny", "Value": "any", "Docs": "" }, { "Name": "AttachmentImage", "Value": "image", "Docs": "" }, { "Name": "AttachmentPDF", "Value": "pdf", "Docs": "" }, { "Name": "AttachmentArchive", "Value": "archive", "Docs": "" }, { "Name": "AttachmentSpreadsheet", "Value": "spreadsheet", "Docs": "" }, { "Name": "AttachmentDocument", "Value": "document", "Docs": "" }, { "Name": "AttachmentPresentation", "Value": "presentation", "Docs": "" }] },
|
||||||
"SecurityResult": { "Name": "SecurityResult", "Docs": "", "Values": [{ "Name": "SecurityResultError", "Value": "error", "Docs": "" }, { "Name": "SecurityResultNo", "Value": "no", "Docs": "" }, { "Name": "SecurityResultYes", "Value": "yes", "Docs": "" }, { "Name": "SecurityResultUnknown", "Value": "unknown", "Docs": "" }] },
|
"SecurityResult": { "Name": "SecurityResult", "Docs": "", "Values": [{ "Name": "SecurityResultError", "Value": "error", "Docs": "" }, { "Name": "SecurityResultNo", "Value": "no", "Docs": "" }, { "Name": "SecurityResultYes", "Value": "yes", "Docs": "" }, { "Name": "SecurityResultUnknown", "Value": "unknown", "Docs": "" }] },
|
||||||
|
"Quoting": { "Name": "Quoting", "Docs": "", "Values": [{ "Name": "Default", "Value": "", "Docs": "" }, { "Name": "Bottom", "Value": "bottom", "Docs": "" }, { "Name": "Top", "Value": "top", "Docs": "" }] },
|
||||||
"Localpart": { "Name": "Localpart", "Docs": "", "Values": null },
|
"Localpart": { "Name": "Localpart", "Docs": "", "Values": null },
|
||||||
};
|
};
|
||||||
api.parser = {
|
api.parser = {
|
||||||
|
@ -342,6 +351,7 @@ var api;
|
||||||
ForwardAttachments: (v) => api.parse("ForwardAttachments", v),
|
ForwardAttachments: (v) => api.parse("ForwardAttachments", v),
|
||||||
Mailbox: (v) => api.parse("Mailbox", v),
|
Mailbox: (v) => api.parse("Mailbox", v),
|
||||||
RecipientSecurity: (v) => api.parse("RecipientSecurity", v),
|
RecipientSecurity: (v) => api.parse("RecipientSecurity", v),
|
||||||
|
Settings: (v) => api.parse("Settings", v),
|
||||||
EventStart: (v) => api.parse("EventStart", v),
|
EventStart: (v) => api.parse("EventStart", v),
|
||||||
DomainAddressConfig: (v) => api.parse("DomainAddressConfig", v),
|
DomainAddressConfig: (v) => api.parse("DomainAddressConfig", v),
|
||||||
EventViewErr: (v) => api.parse("EventViewErr", v),
|
EventViewErr: (v) => api.parse("EventViewErr", v),
|
||||||
|
@ -371,6 +381,7 @@ var api;
|
||||||
ThreadMode: (v) => api.parse("ThreadMode", v),
|
ThreadMode: (v) => api.parse("ThreadMode", v),
|
||||||
AttachmentType: (v) => api.parse("AttachmentType", v),
|
AttachmentType: (v) => api.parse("AttachmentType", v),
|
||||||
SecurityResult: (v) => api.parse("SecurityResult", v),
|
SecurityResult: (v) => api.parse("SecurityResult", v),
|
||||||
|
Quoting: (v) => api.parse("Quoting", v),
|
||||||
Localpart: (v) => api.parse("Localpart", v),
|
Localpart: (v) => api.parse("Localpart", v),
|
||||||
};
|
};
|
||||||
let defaultOptions = { slicesNullable: true, mapsNullable: true, nullableOptional: true };
|
let defaultOptions = { slicesNullable: true, mapsNullable: true, nullableOptional: true };
|
||||||
|
@ -588,6 +599,14 @@ var api;
|
||||||
const params = [text];
|
const params = [text];
|
||||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
}
|
}
|
||||||
|
// SettingsSave saves settings, e.g. for composing.
|
||||||
|
async SettingsSave(settings) {
|
||||||
|
const fn = "SettingsSave";
|
||||||
|
const paramTypes = [["Settings"]];
|
||||||
|
const returnTypes = [];
|
||||||
|
const params = [settings];
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
|
}
|
||||||
// SSETypes exists to ensure the generated API contains the types, for use in SSE events.
|
// SSETypes exists to ensure the generated API contains the types, for use in SSE events.
|
||||||
async SSETypes() {
|
async SSETypes() {
|
||||||
const fn = "SSETypes";
|
const fn = "SSETypes";
|
||||||
|
|
|
@ -274,8 +274,15 @@ var api;
|
||||||
// lookups.
|
// lookups.
|
||||||
SecurityResult["SecurityResultUnknown"] = "unknown";
|
SecurityResult["SecurityResultUnknown"] = "unknown";
|
||||||
})(SecurityResult = api.SecurityResult || (api.SecurityResult = {}));
|
})(SecurityResult = api.SecurityResult || (api.SecurityResult = {}));
|
||||||
api.structTypes = { "Address": true, "Attachment": true, "ChangeMailboxAdd": true, "ChangeMailboxCounts": true, "ChangeMailboxKeywords": true, "ChangeMailboxRemove": true, "ChangeMailboxRename": true, "ChangeMailboxSpecialUse": true, "ChangeMsgAdd": true, "ChangeMsgFlags": true, "ChangeMsgRemove": true, "ChangeMsgThread": true, "Domain": true, "DomainAddressConfig": true, "Envelope": true, "EventStart": true, "EventViewChanges": true, "EventViewErr": true, "EventViewMsgs": true, "EventViewReset": true, "File": true, "Filter": true, "Flags": true, "ForwardAttachments": true, "Mailbox": true, "Message": true, "MessageAddress": true, "MessageEnvelope": true, "MessageItem": true, "NotFilter": true, "Page": true, "ParsedMessage": true, "Part": true, "Query": true, "RecipientSecurity": true, "Request": true, "SpecialUse": true, "SubmitMessage": true };
|
// Quoting is a setting for how to quote in replies/forwards.
|
||||||
api.stringsTypes = { "AttachmentType": true, "CSRFToken": true, "Localpart": true, "SecurityResult": true, "ThreadMode": true };
|
let Quoting;
|
||||||
|
(function (Quoting) {
|
||||||
|
Quoting["Default"] = "";
|
||||||
|
Quoting["Bottom"] = "bottom";
|
||||||
|
Quoting["Top"] = "top";
|
||||||
|
})(Quoting = api.Quoting || (api.Quoting = {}));
|
||||||
|
api.structTypes = { "Address": true, "Attachment": true, "ChangeMailboxAdd": true, "ChangeMailboxCounts": true, "ChangeMailboxKeywords": true, "ChangeMailboxRemove": true, "ChangeMailboxRename": true, "ChangeMailboxSpecialUse": true, "ChangeMsgAdd": true, "ChangeMsgFlags": true, "ChangeMsgRemove": true, "ChangeMsgThread": true, "Domain": true, "DomainAddressConfig": true, "Envelope": true, "EventStart": true, "EventViewChanges": true, "EventViewErr": true, "EventViewMsgs": true, "EventViewReset": true, "File": true, "Filter": true, "Flags": true, "ForwardAttachments": true, "Mailbox": true, "Message": true, "MessageAddress": true, "MessageEnvelope": true, "MessageItem": true, "NotFilter": true, "Page": true, "ParsedMessage": true, "Part": true, "Query": true, "RecipientSecurity": true, "Request": true, "Settings": true, "SpecialUse": true, "SubmitMessage": true };
|
||||||
|
api.stringsTypes = { "AttachmentType": true, "CSRFToken": true, "Localpart": true, "Quoting": true, "SecurityResult": true, "ThreadMode": true };
|
||||||
api.intsTypes = { "ModSeq": true, "UID": true, "Validation": true };
|
api.intsTypes = { "ModSeq": true, "UID": true, "Validation": true };
|
||||||
api.types = {
|
api.types = {
|
||||||
"Request": { "Name": "Request", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Cancel", "Docs": "", "Typewords": ["bool"] }, { "Name": "Query", "Docs": "", "Typewords": ["Query"] }, { "Name": "Page", "Docs": "", "Typewords": ["Page"] }] },
|
"Request": { "Name": "Request", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Cancel", "Docs": "", "Typewords": ["bool"] }, { "Name": "Query", "Docs": "", "Typewords": ["Query"] }, { "Name": "Page", "Docs": "", "Typewords": ["Page"] }] },
|
||||||
|
@ -294,7 +301,8 @@ var api;
|
||||||
"ForwardAttachments": { "Name": "ForwardAttachments", "Docs": "", "Fields": [{ "Name": "MessageID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Paths", "Docs": "", "Typewords": ["[]", "[]", "int32"] }] },
|
"ForwardAttachments": { "Name": "ForwardAttachments", "Docs": "", "Fields": [{ "Name": "MessageID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Paths", "Docs": "", "Typewords": ["[]", "[]", "int32"] }] },
|
||||||
"Mailbox": { "Name": "Mailbox", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "UIDValidity", "Docs": "", "Typewords": ["uint32"] }, { "Name": "UIDNext", "Docs": "", "Typewords": ["UID"] }, { "Name": "Archive", "Docs": "", "Typewords": ["bool"] }, { "Name": "Draft", "Docs": "", "Typewords": ["bool"] }, { "Name": "Junk", "Docs": "", "Typewords": ["bool"] }, { "Name": "Sent", "Docs": "", "Typewords": ["bool"] }, { "Name": "Trash", "Docs": "", "Typewords": ["bool"] }, { "Name": "Keywords", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "HaveCounts", "Docs": "", "Typewords": ["bool"] }, { "Name": "Total", "Docs": "", "Typewords": ["int64"] }, { "Name": "Deleted", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unread", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unseen", "Docs": "", "Typewords": ["int64"] }, { "Name": "Size", "Docs": "", "Typewords": ["int64"] }] },
|
"Mailbox": { "Name": "Mailbox", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "UIDValidity", "Docs": "", "Typewords": ["uint32"] }, { "Name": "UIDNext", "Docs": "", "Typewords": ["UID"] }, { "Name": "Archive", "Docs": "", "Typewords": ["bool"] }, { "Name": "Draft", "Docs": "", "Typewords": ["bool"] }, { "Name": "Junk", "Docs": "", "Typewords": ["bool"] }, { "Name": "Sent", "Docs": "", "Typewords": ["bool"] }, { "Name": "Trash", "Docs": "", "Typewords": ["bool"] }, { "Name": "Keywords", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "HaveCounts", "Docs": "", "Typewords": ["bool"] }, { "Name": "Total", "Docs": "", "Typewords": ["int64"] }, { "Name": "Deleted", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unread", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unseen", "Docs": "", "Typewords": ["int64"] }, { "Name": "Size", "Docs": "", "Typewords": ["int64"] }] },
|
||||||
"RecipientSecurity": { "Name": "RecipientSecurity", "Docs": "", "Fields": [{ "Name": "STARTTLS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "MTASTS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DNSSEC", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DANE", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "RequireTLS", "Docs": "", "Typewords": ["SecurityResult"] }] },
|
"RecipientSecurity": { "Name": "RecipientSecurity", "Docs": "", "Fields": [{ "Name": "STARTTLS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "MTASTS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DNSSEC", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DANE", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "RequireTLS", "Docs": "", "Typewords": ["SecurityResult"] }] },
|
||||||
"EventStart": { "Name": "EventStart", "Docs": "", "Fields": [{ "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "LoginAddress", "Docs": "", "Typewords": ["MessageAddress"] }, { "Name": "Addresses", "Docs": "", "Typewords": ["[]", "MessageAddress"] }, { "Name": "DomainAddressConfigs", "Docs": "", "Typewords": ["{}", "DomainAddressConfig"] }, { "Name": "MailboxName", "Docs": "", "Typewords": ["string"] }, { "Name": "Mailboxes", "Docs": "", "Typewords": ["[]", "Mailbox"] }, { "Name": "RejectsMailbox", "Docs": "", "Typewords": ["string"] }, { "Name": "Version", "Docs": "", "Typewords": ["string"] }] },
|
"Settings": { "Name": "Settings", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["uint8"] }, { "Name": "Signature", "Docs": "", "Typewords": ["string"] }, { "Name": "Quoting", "Docs": "", "Typewords": ["Quoting"] }, { "Name": "ShowAddressSecurity", "Docs": "", "Typewords": ["bool"] }] },
|
||||||
|
"EventStart": { "Name": "EventStart", "Docs": "", "Fields": [{ "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "LoginAddress", "Docs": "", "Typewords": ["MessageAddress"] }, { "Name": "Addresses", "Docs": "", "Typewords": ["[]", "MessageAddress"] }, { "Name": "DomainAddressConfigs", "Docs": "", "Typewords": ["{}", "DomainAddressConfig"] }, { "Name": "MailboxName", "Docs": "", "Typewords": ["string"] }, { "Name": "Mailboxes", "Docs": "", "Typewords": ["[]", "Mailbox"] }, { "Name": "RejectsMailbox", "Docs": "", "Typewords": ["string"] }, { "Name": "Settings", "Docs": "", "Typewords": ["Settings"] }, { "Name": "Version", "Docs": "", "Typewords": ["string"] }] },
|
||||||
"DomainAddressConfig": { "Name": "DomainAddressConfig", "Docs": "", "Fields": [{ "Name": "LocalpartCatchallSeparator", "Docs": "", "Typewords": ["string"] }, { "Name": "LocalpartCaseSensitive", "Docs": "", "Typewords": ["bool"] }] },
|
"DomainAddressConfig": { "Name": "DomainAddressConfig", "Docs": "", "Fields": [{ "Name": "LocalpartCatchallSeparator", "Docs": "", "Typewords": ["string"] }, { "Name": "LocalpartCaseSensitive", "Docs": "", "Typewords": ["bool"] }] },
|
||||||
"EventViewErr": { "Name": "EventViewErr", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Err", "Docs": "", "Typewords": ["string"] }] },
|
"EventViewErr": { "Name": "EventViewErr", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Err", "Docs": "", "Typewords": ["string"] }] },
|
||||||
"EventViewReset": { "Name": "EventViewReset", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }] },
|
"EventViewReset": { "Name": "EventViewReset", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }] },
|
||||||
|
@ -323,6 +331,7 @@ var api;
|
||||||
"ThreadMode": { "Name": "ThreadMode", "Docs": "", "Values": [{ "Name": "ThreadOff", "Value": "off", "Docs": "" }, { "Name": "ThreadOn", "Value": "on", "Docs": "" }, { "Name": "ThreadUnread", "Value": "unread", "Docs": "" }] },
|
"ThreadMode": { "Name": "ThreadMode", "Docs": "", "Values": [{ "Name": "ThreadOff", "Value": "off", "Docs": "" }, { "Name": "ThreadOn", "Value": "on", "Docs": "" }, { "Name": "ThreadUnread", "Value": "unread", "Docs": "" }] },
|
||||||
"AttachmentType": { "Name": "AttachmentType", "Docs": "", "Values": [{ "Name": "AttachmentIndifferent", "Value": "", "Docs": "" }, { "Name": "AttachmentNone", "Value": "none", "Docs": "" }, { "Name": "AttachmentAny", "Value": "any", "Docs": "" }, { "Name": "AttachmentImage", "Value": "image", "Docs": "" }, { "Name": "AttachmentPDF", "Value": "pdf", "Docs": "" }, { "Name": "AttachmentArchive", "Value": "archive", "Docs": "" }, { "Name": "AttachmentSpreadsheet", "Value": "spreadsheet", "Docs": "" }, { "Name": "AttachmentDocument", "Value": "document", "Docs": "" }, { "Name": "AttachmentPresentation", "Value": "presentation", "Docs": "" }] },
|
"AttachmentType": { "Name": "AttachmentType", "Docs": "", "Values": [{ "Name": "AttachmentIndifferent", "Value": "", "Docs": "" }, { "Name": "AttachmentNone", "Value": "none", "Docs": "" }, { "Name": "AttachmentAny", "Value": "any", "Docs": "" }, { "Name": "AttachmentImage", "Value": "image", "Docs": "" }, { "Name": "AttachmentPDF", "Value": "pdf", "Docs": "" }, { "Name": "AttachmentArchive", "Value": "archive", "Docs": "" }, { "Name": "AttachmentSpreadsheet", "Value": "spreadsheet", "Docs": "" }, { "Name": "AttachmentDocument", "Value": "document", "Docs": "" }, { "Name": "AttachmentPresentation", "Value": "presentation", "Docs": "" }] },
|
||||||
"SecurityResult": { "Name": "SecurityResult", "Docs": "", "Values": [{ "Name": "SecurityResultError", "Value": "error", "Docs": "" }, { "Name": "SecurityResultNo", "Value": "no", "Docs": "" }, { "Name": "SecurityResultYes", "Value": "yes", "Docs": "" }, { "Name": "SecurityResultUnknown", "Value": "unknown", "Docs": "" }] },
|
"SecurityResult": { "Name": "SecurityResult", "Docs": "", "Values": [{ "Name": "SecurityResultError", "Value": "error", "Docs": "" }, { "Name": "SecurityResultNo", "Value": "no", "Docs": "" }, { "Name": "SecurityResultYes", "Value": "yes", "Docs": "" }, { "Name": "SecurityResultUnknown", "Value": "unknown", "Docs": "" }] },
|
||||||
|
"Quoting": { "Name": "Quoting", "Docs": "", "Values": [{ "Name": "Default", "Value": "", "Docs": "" }, { "Name": "Bottom", "Value": "bottom", "Docs": "" }, { "Name": "Top", "Value": "top", "Docs": "" }] },
|
||||||
"Localpart": { "Name": "Localpart", "Docs": "", "Values": null },
|
"Localpart": { "Name": "Localpart", "Docs": "", "Values": null },
|
||||||
};
|
};
|
||||||
api.parser = {
|
api.parser = {
|
||||||
|
@ -342,6 +351,7 @@ var api;
|
||||||
ForwardAttachments: (v) => api.parse("ForwardAttachments", v),
|
ForwardAttachments: (v) => api.parse("ForwardAttachments", v),
|
||||||
Mailbox: (v) => api.parse("Mailbox", v),
|
Mailbox: (v) => api.parse("Mailbox", v),
|
||||||
RecipientSecurity: (v) => api.parse("RecipientSecurity", v),
|
RecipientSecurity: (v) => api.parse("RecipientSecurity", v),
|
||||||
|
Settings: (v) => api.parse("Settings", v),
|
||||||
EventStart: (v) => api.parse("EventStart", v),
|
EventStart: (v) => api.parse("EventStart", v),
|
||||||
DomainAddressConfig: (v) => api.parse("DomainAddressConfig", v),
|
DomainAddressConfig: (v) => api.parse("DomainAddressConfig", v),
|
||||||
EventViewErr: (v) => api.parse("EventViewErr", v),
|
EventViewErr: (v) => api.parse("EventViewErr", v),
|
||||||
|
@ -371,6 +381,7 @@ var api;
|
||||||
ThreadMode: (v) => api.parse("ThreadMode", v),
|
ThreadMode: (v) => api.parse("ThreadMode", v),
|
||||||
AttachmentType: (v) => api.parse("AttachmentType", v),
|
AttachmentType: (v) => api.parse("AttachmentType", v),
|
||||||
SecurityResult: (v) => api.parse("SecurityResult", v),
|
SecurityResult: (v) => api.parse("SecurityResult", v),
|
||||||
|
Quoting: (v) => api.parse("Quoting", v),
|
||||||
Localpart: (v) => api.parse("Localpart", v),
|
Localpart: (v) => api.parse("Localpart", v),
|
||||||
};
|
};
|
||||||
let defaultOptions = { slicesNullable: true, mapsNullable: true, nullableOptional: true };
|
let defaultOptions = { slicesNullable: true, mapsNullable: true, nullableOptional: true };
|
||||||
|
@ -588,6 +599,14 @@ var api;
|
||||||
const params = [text];
|
const params = [text];
|
||||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
}
|
}
|
||||||
|
// SettingsSave saves settings, e.g. for composing.
|
||||||
|
async SettingsSave(settings) {
|
||||||
|
const fn = "SettingsSave";
|
||||||
|
const paramTypes = [["Settings"]];
|
||||||
|
const returnTypes = [];
|
||||||
|
const params = [settings];
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
|
}
|
||||||
// SSETypes exists to ensure the generated API contains the types, for use in SSE events.
|
// SSETypes exists to ensure the generated API contains the types, for use in SSE events.
|
||||||
async SSETypes() {
|
async SSETypes() {
|
||||||
const fn = "SSETypes";
|
const fn = "SSETypes";
|
||||||
|
|
|
@ -215,6 +215,7 @@ type EventStart struct {
|
||||||
MailboxName string
|
MailboxName string
|
||||||
Mailboxes []store.Mailbox
|
Mailboxes []store.Mailbox
|
||||||
RejectsMailbox string
|
RejectsMailbox string
|
||||||
|
Settings store.Settings
|
||||||
Version string
|
Version string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,6 +665,7 @@ func serveEvents(ctx context.Context, log mlog.Log, w http.ResponseWriter, r *ht
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var mbl []store.Mailbox
|
var mbl []store.Mailbox
|
||||||
|
settings := store.Settings{ID: 1}
|
||||||
|
|
||||||
// We only take the rlock when getting the tx.
|
// We only take the rlock when getting the tx.
|
||||||
acc.WithRLock(func() {
|
acc.WithRLock(func() {
|
||||||
|
@ -673,6 +675,9 @@ func serveEvents(ctx context.Context, log mlog.Log, w http.ResponseWriter, r *ht
|
||||||
|
|
||||||
mbl, err = bstore.QueryTx[store.Mailbox](qtx).List()
|
mbl, err = bstore.QueryTx[store.Mailbox](qtx).List()
|
||||||
xcheckf(ctx, err, "list mailboxes")
|
xcheckf(ctx, err, "list mailboxes")
|
||||||
|
|
||||||
|
err = qtx.Get(&settings)
|
||||||
|
xcheckf(ctx, err, "get settings")
|
||||||
})
|
})
|
||||||
|
|
||||||
// Find the designated mailbox if a mailbox name is set, or there are no filters at all.
|
// Find the designated mailbox if a mailbox name is set, or there are no filters at all.
|
||||||
|
@ -728,7 +733,7 @@ func serveEvents(ctx context.Context, log mlog.Log, w http.ResponseWriter, r *ht
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write first event, allowing client to fill its UI with mailboxes.
|
// Write first event, allowing client to fill its UI with mailboxes.
|
||||||
start := EventStart{sse.ID, loginAddress, addresses, domainAddressConfigs, mailbox.Name, mbl, accConf.RejectsMailbox, moxvar.Version}
|
start := EventStart{sse.ID, loginAddress, addresses, domainAddressConfigs, mailbox.Name, mbl, accConf.RejectsMailbox, settings, moxvar.Version}
|
||||||
writer.xsendEvent(ctx, log, "start", start)
|
writer.xsendEvent(ctx, log, "start", start)
|
||||||
|
|
||||||
// The goroutine doing the querying will send messages on these channels, which
|
// The goroutine doing the querying will send messages on these channels, which
|
||||||
|
|
|
@ -274,8 +274,15 @@ var api;
|
||||||
// lookups.
|
// lookups.
|
||||||
SecurityResult["SecurityResultUnknown"] = "unknown";
|
SecurityResult["SecurityResultUnknown"] = "unknown";
|
||||||
})(SecurityResult = api.SecurityResult || (api.SecurityResult = {}));
|
})(SecurityResult = api.SecurityResult || (api.SecurityResult = {}));
|
||||||
api.structTypes = { "Address": true, "Attachment": true, "ChangeMailboxAdd": true, "ChangeMailboxCounts": true, "ChangeMailboxKeywords": true, "ChangeMailboxRemove": true, "ChangeMailboxRename": true, "ChangeMailboxSpecialUse": true, "ChangeMsgAdd": true, "ChangeMsgFlags": true, "ChangeMsgRemove": true, "ChangeMsgThread": true, "Domain": true, "DomainAddressConfig": true, "Envelope": true, "EventStart": true, "EventViewChanges": true, "EventViewErr": true, "EventViewMsgs": true, "EventViewReset": true, "File": true, "Filter": true, "Flags": true, "ForwardAttachments": true, "Mailbox": true, "Message": true, "MessageAddress": true, "MessageEnvelope": true, "MessageItem": true, "NotFilter": true, "Page": true, "ParsedMessage": true, "Part": true, "Query": true, "RecipientSecurity": true, "Request": true, "SpecialUse": true, "SubmitMessage": true };
|
// Quoting is a setting for how to quote in replies/forwards.
|
||||||
api.stringsTypes = { "AttachmentType": true, "CSRFToken": true, "Localpart": true, "SecurityResult": true, "ThreadMode": true };
|
let Quoting;
|
||||||
|
(function (Quoting) {
|
||||||
|
Quoting["Default"] = "";
|
||||||
|
Quoting["Bottom"] = "bottom";
|
||||||
|
Quoting["Top"] = "top";
|
||||||
|
})(Quoting = api.Quoting || (api.Quoting = {}));
|
||||||
|
api.structTypes = { "Address": true, "Attachment": true, "ChangeMailboxAdd": true, "ChangeMailboxCounts": true, "ChangeMailboxKeywords": true, "ChangeMailboxRemove": true, "ChangeMailboxRename": true, "ChangeMailboxSpecialUse": true, "ChangeMsgAdd": true, "ChangeMsgFlags": true, "ChangeMsgRemove": true, "ChangeMsgThread": true, "Domain": true, "DomainAddressConfig": true, "Envelope": true, "EventStart": true, "EventViewChanges": true, "EventViewErr": true, "EventViewMsgs": true, "EventViewReset": true, "File": true, "Filter": true, "Flags": true, "ForwardAttachments": true, "Mailbox": true, "Message": true, "MessageAddress": true, "MessageEnvelope": true, "MessageItem": true, "NotFilter": true, "Page": true, "ParsedMessage": true, "Part": true, "Query": true, "RecipientSecurity": true, "Request": true, "Settings": true, "SpecialUse": true, "SubmitMessage": true };
|
||||||
|
api.stringsTypes = { "AttachmentType": true, "CSRFToken": true, "Localpart": true, "Quoting": true, "SecurityResult": true, "ThreadMode": true };
|
||||||
api.intsTypes = { "ModSeq": true, "UID": true, "Validation": true };
|
api.intsTypes = { "ModSeq": true, "UID": true, "Validation": true };
|
||||||
api.types = {
|
api.types = {
|
||||||
"Request": { "Name": "Request", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Cancel", "Docs": "", "Typewords": ["bool"] }, { "Name": "Query", "Docs": "", "Typewords": ["Query"] }, { "Name": "Page", "Docs": "", "Typewords": ["Page"] }] },
|
"Request": { "Name": "Request", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Cancel", "Docs": "", "Typewords": ["bool"] }, { "Name": "Query", "Docs": "", "Typewords": ["Query"] }, { "Name": "Page", "Docs": "", "Typewords": ["Page"] }] },
|
||||||
|
@ -294,7 +301,8 @@ var api;
|
||||||
"ForwardAttachments": { "Name": "ForwardAttachments", "Docs": "", "Fields": [{ "Name": "MessageID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Paths", "Docs": "", "Typewords": ["[]", "[]", "int32"] }] },
|
"ForwardAttachments": { "Name": "ForwardAttachments", "Docs": "", "Fields": [{ "Name": "MessageID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Paths", "Docs": "", "Typewords": ["[]", "[]", "int32"] }] },
|
||||||
"Mailbox": { "Name": "Mailbox", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "UIDValidity", "Docs": "", "Typewords": ["uint32"] }, { "Name": "UIDNext", "Docs": "", "Typewords": ["UID"] }, { "Name": "Archive", "Docs": "", "Typewords": ["bool"] }, { "Name": "Draft", "Docs": "", "Typewords": ["bool"] }, { "Name": "Junk", "Docs": "", "Typewords": ["bool"] }, { "Name": "Sent", "Docs": "", "Typewords": ["bool"] }, { "Name": "Trash", "Docs": "", "Typewords": ["bool"] }, { "Name": "Keywords", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "HaveCounts", "Docs": "", "Typewords": ["bool"] }, { "Name": "Total", "Docs": "", "Typewords": ["int64"] }, { "Name": "Deleted", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unread", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unseen", "Docs": "", "Typewords": ["int64"] }, { "Name": "Size", "Docs": "", "Typewords": ["int64"] }] },
|
"Mailbox": { "Name": "Mailbox", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "UIDValidity", "Docs": "", "Typewords": ["uint32"] }, { "Name": "UIDNext", "Docs": "", "Typewords": ["UID"] }, { "Name": "Archive", "Docs": "", "Typewords": ["bool"] }, { "Name": "Draft", "Docs": "", "Typewords": ["bool"] }, { "Name": "Junk", "Docs": "", "Typewords": ["bool"] }, { "Name": "Sent", "Docs": "", "Typewords": ["bool"] }, { "Name": "Trash", "Docs": "", "Typewords": ["bool"] }, { "Name": "Keywords", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "HaveCounts", "Docs": "", "Typewords": ["bool"] }, { "Name": "Total", "Docs": "", "Typewords": ["int64"] }, { "Name": "Deleted", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unread", "Docs": "", "Typewords": ["int64"] }, { "Name": "Unseen", "Docs": "", "Typewords": ["int64"] }, { "Name": "Size", "Docs": "", "Typewords": ["int64"] }] },
|
||||||
"RecipientSecurity": { "Name": "RecipientSecurity", "Docs": "", "Fields": [{ "Name": "STARTTLS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "MTASTS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DNSSEC", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DANE", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "RequireTLS", "Docs": "", "Typewords": ["SecurityResult"] }] },
|
"RecipientSecurity": { "Name": "RecipientSecurity", "Docs": "", "Fields": [{ "Name": "STARTTLS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "MTASTS", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DNSSEC", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "DANE", "Docs": "", "Typewords": ["SecurityResult"] }, { "Name": "RequireTLS", "Docs": "", "Typewords": ["SecurityResult"] }] },
|
||||||
"EventStart": { "Name": "EventStart", "Docs": "", "Fields": [{ "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "LoginAddress", "Docs": "", "Typewords": ["MessageAddress"] }, { "Name": "Addresses", "Docs": "", "Typewords": ["[]", "MessageAddress"] }, { "Name": "DomainAddressConfigs", "Docs": "", "Typewords": ["{}", "DomainAddressConfig"] }, { "Name": "MailboxName", "Docs": "", "Typewords": ["string"] }, { "Name": "Mailboxes", "Docs": "", "Typewords": ["[]", "Mailbox"] }, { "Name": "RejectsMailbox", "Docs": "", "Typewords": ["string"] }, { "Name": "Version", "Docs": "", "Typewords": ["string"] }] },
|
"Settings": { "Name": "Settings", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["uint8"] }, { "Name": "Signature", "Docs": "", "Typewords": ["string"] }, { "Name": "Quoting", "Docs": "", "Typewords": ["Quoting"] }, { "Name": "ShowAddressSecurity", "Docs": "", "Typewords": ["bool"] }] },
|
||||||
|
"EventStart": { "Name": "EventStart", "Docs": "", "Fields": [{ "Name": "SSEID", "Docs": "", "Typewords": ["int64"] }, { "Name": "LoginAddress", "Docs": "", "Typewords": ["MessageAddress"] }, { "Name": "Addresses", "Docs": "", "Typewords": ["[]", "MessageAddress"] }, { "Name": "DomainAddressConfigs", "Docs": "", "Typewords": ["{}", "DomainAddressConfig"] }, { "Name": "MailboxName", "Docs": "", "Typewords": ["string"] }, { "Name": "Mailboxes", "Docs": "", "Typewords": ["[]", "Mailbox"] }, { "Name": "RejectsMailbox", "Docs": "", "Typewords": ["string"] }, { "Name": "Settings", "Docs": "", "Typewords": ["Settings"] }, { "Name": "Version", "Docs": "", "Typewords": ["string"] }] },
|
||||||
"DomainAddressConfig": { "Name": "DomainAddressConfig", "Docs": "", "Fields": [{ "Name": "LocalpartCatchallSeparator", "Docs": "", "Typewords": ["string"] }, { "Name": "LocalpartCaseSensitive", "Docs": "", "Typewords": ["bool"] }] },
|
"DomainAddressConfig": { "Name": "DomainAddressConfig", "Docs": "", "Fields": [{ "Name": "LocalpartCatchallSeparator", "Docs": "", "Typewords": ["string"] }, { "Name": "LocalpartCaseSensitive", "Docs": "", "Typewords": ["bool"] }] },
|
||||||
"EventViewErr": { "Name": "EventViewErr", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Err", "Docs": "", "Typewords": ["string"] }] },
|
"EventViewErr": { "Name": "EventViewErr", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Err", "Docs": "", "Typewords": ["string"] }] },
|
||||||
"EventViewReset": { "Name": "EventViewReset", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }] },
|
"EventViewReset": { "Name": "EventViewReset", "Docs": "", "Fields": [{ "Name": "ViewID", "Docs": "", "Typewords": ["int64"] }, { "Name": "RequestID", "Docs": "", "Typewords": ["int64"] }] },
|
||||||
|
@ -323,6 +331,7 @@ var api;
|
||||||
"ThreadMode": { "Name": "ThreadMode", "Docs": "", "Values": [{ "Name": "ThreadOff", "Value": "off", "Docs": "" }, { "Name": "ThreadOn", "Value": "on", "Docs": "" }, { "Name": "ThreadUnread", "Value": "unread", "Docs": "" }] },
|
"ThreadMode": { "Name": "ThreadMode", "Docs": "", "Values": [{ "Name": "ThreadOff", "Value": "off", "Docs": "" }, { "Name": "ThreadOn", "Value": "on", "Docs": "" }, { "Name": "ThreadUnread", "Value": "unread", "Docs": "" }] },
|
||||||
"AttachmentType": { "Name": "AttachmentType", "Docs": "", "Values": [{ "Name": "AttachmentIndifferent", "Value": "", "Docs": "" }, { "Name": "AttachmentNone", "Value": "none", "Docs": "" }, { "Name": "AttachmentAny", "Value": "any", "Docs": "" }, { "Name": "AttachmentImage", "Value": "image", "Docs": "" }, { "Name": "AttachmentPDF", "Value": "pdf", "Docs": "" }, { "Name": "AttachmentArchive", "Value": "archive", "Docs": "" }, { "Name": "AttachmentSpreadsheet", "Value": "spreadsheet", "Docs": "" }, { "Name": "AttachmentDocument", "Value": "document", "Docs": "" }, { "Name": "AttachmentPresentation", "Value": "presentation", "Docs": "" }] },
|
"AttachmentType": { "Name": "AttachmentType", "Docs": "", "Values": [{ "Name": "AttachmentIndifferent", "Value": "", "Docs": "" }, { "Name": "AttachmentNone", "Value": "none", "Docs": "" }, { "Name": "AttachmentAny", "Value": "any", "Docs": "" }, { "Name": "AttachmentImage", "Value": "image", "Docs": "" }, { "Name": "AttachmentPDF", "Value": "pdf", "Docs": "" }, { "Name": "AttachmentArchive", "Value": "archive", "Docs": "" }, { "Name": "AttachmentSpreadsheet", "Value": "spreadsheet", "Docs": "" }, { "Name": "AttachmentDocument", "Value": "document", "Docs": "" }, { "Name": "AttachmentPresentation", "Value": "presentation", "Docs": "" }] },
|
||||||
"SecurityResult": { "Name": "SecurityResult", "Docs": "", "Values": [{ "Name": "SecurityResultError", "Value": "error", "Docs": "" }, { "Name": "SecurityResultNo", "Value": "no", "Docs": "" }, { "Name": "SecurityResultYes", "Value": "yes", "Docs": "" }, { "Name": "SecurityResultUnknown", "Value": "unknown", "Docs": "" }] },
|
"SecurityResult": { "Name": "SecurityResult", "Docs": "", "Values": [{ "Name": "SecurityResultError", "Value": "error", "Docs": "" }, { "Name": "SecurityResultNo", "Value": "no", "Docs": "" }, { "Name": "SecurityResultYes", "Value": "yes", "Docs": "" }, { "Name": "SecurityResultUnknown", "Value": "unknown", "Docs": "" }] },
|
||||||
|
"Quoting": { "Name": "Quoting", "Docs": "", "Values": [{ "Name": "Default", "Value": "", "Docs": "" }, { "Name": "Bottom", "Value": "bottom", "Docs": "" }, { "Name": "Top", "Value": "top", "Docs": "" }] },
|
||||||
"Localpart": { "Name": "Localpart", "Docs": "", "Values": null },
|
"Localpart": { "Name": "Localpart", "Docs": "", "Values": null },
|
||||||
};
|
};
|
||||||
api.parser = {
|
api.parser = {
|
||||||
|
@ -342,6 +351,7 @@ var api;
|
||||||
ForwardAttachments: (v) => api.parse("ForwardAttachments", v),
|
ForwardAttachments: (v) => api.parse("ForwardAttachments", v),
|
||||||
Mailbox: (v) => api.parse("Mailbox", v),
|
Mailbox: (v) => api.parse("Mailbox", v),
|
||||||
RecipientSecurity: (v) => api.parse("RecipientSecurity", v),
|
RecipientSecurity: (v) => api.parse("RecipientSecurity", v),
|
||||||
|
Settings: (v) => api.parse("Settings", v),
|
||||||
EventStart: (v) => api.parse("EventStart", v),
|
EventStart: (v) => api.parse("EventStart", v),
|
||||||
DomainAddressConfig: (v) => api.parse("DomainAddressConfig", v),
|
DomainAddressConfig: (v) => api.parse("DomainAddressConfig", v),
|
||||||
EventViewErr: (v) => api.parse("EventViewErr", v),
|
EventViewErr: (v) => api.parse("EventViewErr", v),
|
||||||
|
@ -371,6 +381,7 @@ var api;
|
||||||
ThreadMode: (v) => api.parse("ThreadMode", v),
|
ThreadMode: (v) => api.parse("ThreadMode", v),
|
||||||
AttachmentType: (v) => api.parse("AttachmentType", v),
|
AttachmentType: (v) => api.parse("AttachmentType", v),
|
||||||
SecurityResult: (v) => api.parse("SecurityResult", v),
|
SecurityResult: (v) => api.parse("SecurityResult", v),
|
||||||
|
Quoting: (v) => api.parse("Quoting", v),
|
||||||
Localpart: (v) => api.parse("Localpart", v),
|
Localpart: (v) => api.parse("Localpart", v),
|
||||||
};
|
};
|
||||||
let defaultOptions = { slicesNullable: true, mapsNullable: true, nullableOptional: true };
|
let defaultOptions = { slicesNullable: true, mapsNullable: true, nullableOptional: true };
|
||||||
|
@ -588,6 +599,14 @@ var api;
|
||||||
const params = [text];
|
const params = [text];
|
||||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
}
|
}
|
||||||
|
// SettingsSave saves settings, e.g. for composing.
|
||||||
|
async SettingsSave(settings) {
|
||||||
|
const fn = "SettingsSave";
|
||||||
|
const paramTypes = [["Settings"]];
|
||||||
|
const returnTypes = [];
|
||||||
|
const params = [settings];
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
|
}
|
||||||
// SSETypes exists to ensure the generated API contains the types, for use in SSE events.
|
// SSETypes exists to ensure the generated API contains the types, for use in SSE events.
|
||||||
async SSETypes() {
|
async SSETypes() {
|
||||||
const fn = "SSETypes";
|
const fn = "SSETypes";
|
||||||
|
@ -1257,6 +1276,7 @@ try {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) { }
|
catch (err) { }
|
||||||
|
let accountSettings;
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
showShortcuts: true,
|
showShortcuts: true,
|
||||||
mailboxesWidth: 240,
|
mailboxesWidth: 240,
|
||||||
|
@ -1981,6 +2001,20 @@ const withStatus = async (action, promise, disablable, noAlert) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const withDisabled = async (elem, p) => {
|
||||||
|
try {
|
||||||
|
elem.disabled = true;
|
||||||
|
return await p;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.log({ err });
|
||||||
|
window.alert('Error: ' + errmsg(err));
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
elem.disabled = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
// Popover shows kids in a div on top of a mostly transparent overlay on top of
|
// Popover shows kids in a div on top of a mostly transparent overlay on top of
|
||||||
// the document. If transparent is set, the div the kids are in will not get a
|
// the document. If transparent is set, the div the kids are in will not get a
|
||||||
// white background. If focus is set, it will be called after adding the
|
// white background. If focus is set, it will be called after adding the
|
||||||
|
@ -2082,6 +2116,29 @@ const popup = (...kids) => {
|
||||||
content.focus();
|
content.focus();
|
||||||
return close;
|
return close;
|
||||||
};
|
};
|
||||||
|
// Show settings screen.
|
||||||
|
const cmdSettings = async () => {
|
||||||
|
let fieldset;
|
||||||
|
let signature;
|
||||||
|
let quoting;
|
||||||
|
let showAddressSecurity;
|
||||||
|
if (!accountSettings) {
|
||||||
|
window.alert('No account settings fetched yet.');
|
||||||
|
}
|
||||||
|
const remove = popup(style({ padding: '1em 1em 2em 1em', minWidth: '30em' }), dom.h1('Settings'), dom.form(async function submit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
const accSet = {
|
||||||
|
ID: accountSettings.ID,
|
||||||
|
Signature: signature.value,
|
||||||
|
Quoting: quoting.value,
|
||||||
|
ShowAddressSecurity: showAddressSecurity.checked,
|
||||||
|
};
|
||||||
|
await withDisabled(fieldset, client.SettingsSave(accSet));
|
||||||
|
accountSettings = accSet;
|
||||||
|
remove();
|
||||||
|
}, fieldset = dom.fieldset(dom.label(style({ margin: '1ex 0', display: 'block' }), dom.div('Signature'), signature = dom.textarea(new String(accountSettings.Signature), style({ width: '100%' }), attr.rows('' + Math.max(3, 1 + accountSettings.Signature.split('\n').length)))), dom.label(style({ margin: '1ex 0', display: 'block' }), dom.div('Reply above/below original'), attr.title('Auto: If text is selected, only the replied text is quoted and editing starts below. Otherwise, the full message is quoted and editing starts at the top.'), quoting = dom.select(dom.option(attr.value(''), 'Auto'), dom.option(attr.value('bottom'), 'Bottom', accountSettings.Quoting === api.Quoting.Bottom ? attr.selected('') : []), dom.option(attr.value('top'), 'Top', accountSettings.Quoting === api.Quoting.Top ? attr.selected('') : []))), dom.label(style({ margin: '1ex 0', display: 'block' }), showAddressSecurity = dom.input(attr.type('checkbox'), accountSettings.ShowAddressSecurity ? attr.checked('') : []), ' Show address security indications', attr.title('Show bars underneath address input fields, indicating support for STARTTLS/DNSSEC/DANE/MTA-STS/RequireTLS.')), dom.br(), dom.div(dom.submitbutton('Save')))));
|
||||||
|
};
|
||||||
// Show help popup, with shortcuts and basic explanation.
|
// Show help popup, with shortcuts and basic explanation.
|
||||||
const cmdHelp = async () => {
|
const cmdHelp = async () => {
|
||||||
const remove = popup(style({ padding: '1em 1em 2em 1em' }), dom.h1('Help and keyboard shortcuts'), dom.div(style({ display: 'flex' }), dom.div(style({ width: '40em' }), dom.table(dom.tr(dom.td(attr.colspan('2'), dom.h2('Global', style({ margin: '0' })))), [
|
const remove = popup(style({ padding: '1em 1em 2em 1em' }), dom.h1('Help and keyboard shortcuts'), dom.div(style({ display: 'flex' }), dom.div(style({ width: '40em' }), dom.table(dom.tr(dom.td(attr.colspan('2'), dom.h2('Global', style({ margin: '0' })))), [
|
||||||
|
@ -2328,6 +2385,9 @@ const compose = (opts) => {
|
||||||
let rcptSecAborter = {};
|
let rcptSecAborter = {};
|
||||||
let autosizeElem, inputElem, securityBar;
|
let autosizeElem, inputElem, securityBar;
|
||||||
const fetchRecipientSecurity = () => {
|
const fetchRecipientSecurity = () => {
|
||||||
|
if (!accountSettings?.ShowAddressSecurity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (inputElem.value === rcptSecAddr) {
|
if (inputElem.value === rcptSecAddr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2411,7 +2471,7 @@ const compose = (opts) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const recipientSecurityTitle = 'Description of security mechanisms recipient domains may implement:\n1. STARTTLS: Opportunistic (unverified) TLS with STARTTLS, successfully negotiated during the most recent delivery attempt.\n2. MTA-STS: For PKIX/WebPKI-verified TLS.\n3. DNSSEC: MX DNS records are DNSSEC-signed.\n4. DANE: First delivery destination host implements DANE for verified TLS.\n5. RequireTLS: SMTP extension for verified TLS delivery into recipient mailbox, support detected during the most recent delivery attempt.\n\nChecks STARTTLS, DANE and RequireTLS cover the most recently used delivery path, not necessarily all possible delivery paths.\n\nThe bars below the input field indicate implementation status by the recipient domain:\n- Red, not implemented/unsupported\n- Green, implemented/supported\n- Gray, error while determining\n- Absent/white, unknown or skipped (e.g. no previous delivery attempt, or DANE check skipped due to DNSSEC-lookup error)';
|
const recipientSecurityTitle = 'Description of security mechanisms recipient domains may implement:\n1. STARTTLS: Opportunistic (unverified) TLS with STARTTLS, successfully negotiated during the most recent delivery attempt.\n2. MTA-STS: For PKIX/WebPKI-verified TLS.\n3. DNSSEC: MX DNS records are DNSSEC-signed.\n4. DANE: First delivery destination host implements DANE for verified TLS.\n5. RequireTLS: SMTP extension for verified TLS delivery into recipient mailbox, support detected during the most recent delivery attempt.\n\nChecks STARTTLS, DANE and RequireTLS cover the most recently used delivery path, not necessarily all possible delivery paths.\n\nThe bars below the input field indicate implementation status by the recipient domain:\n- Red, not implemented/unsupported\n- Green, implemented/supported\n- Gray, error while determining\n- Absent/white, unknown or skipped (e.g. no previous delivery attempt, or DANE check skipped due to DNSSEC-lookup error)';
|
||||||
const root = dom.span(autosizeElem = dom.span(dom._class('autosize'), inputElem = dom.input(focusPlaceholder('Jane <jane@example.org>'), style({ width: 'auto' }), attr.value(addr), newAddressComplete(), attr.title(recipientSecurityTitle), function keydown(e) {
|
const root = dom.span(autosizeElem = dom.span(dom._class('autosize'), inputElem = dom.input(focusPlaceholder('Jane <jane@example.org>'), style({ width: 'auto' }), attr.value(addr), newAddressComplete(), accountSettings?.ShowAddressSecurity ? attr.title(recipientSecurityTitle) : [], function keydown(e) {
|
||||||
if (e.key === '-' && e.ctrlKey) {
|
if (e.key === '-' && e.ctrlKey) {
|
||||||
remove();
|
remove();
|
||||||
}
|
}
|
||||||
|
@ -2547,7 +2607,7 @@ const compose = (opts) => {
|
||||||
}))))), body = dom.textarea(dom._class('mono'), attr.rows('15'), style({ width: '100%' }),
|
}))))), body = dom.textarea(dom._class('mono'), attr.rows('15'), style({ width: '100%' }),
|
||||||
// Explicit string object so it doesn't get the highlight-unicode-block-changes
|
// Explicit string object so it doesn't get the highlight-unicode-block-changes
|
||||||
// treatment, which would cause characters to disappear.
|
// treatment, which would cause characters to disappear.
|
||||||
new String(opts.body || ''), opts.body && !opts.isForward && !opts.body.startsWith('\n\n') ? prop({ selectionStart: opts.body.length, selectionEnd: opts.body.length }) : [], function keyup(e) {
|
new String(opts.body || ''), prop({ selectionStart: opts.editOffset || 0, selectionEnd: opts.editOffset || 0 }), function keyup(e) {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
checkAttachments();
|
checkAttachments();
|
||||||
}
|
}
|
||||||
|
@ -3075,13 +3135,17 @@ const newMsgView = (miv, msglistView, listMailboxes, possibleLabels, messageLoad
|
||||||
body = pm.Texts[0];
|
body = pm.Texts[0];
|
||||||
}
|
}
|
||||||
body = body.replace(/\r/g, '').replace(/\n\n\n\n*/g, '\n\n').trim();
|
body = body.replace(/\r/g, '').replace(/\n\n\n\n*/g, '\n\n').trim();
|
||||||
|
let editOffset = 0;
|
||||||
if (forward) {
|
if (forward) {
|
||||||
body = '\n\n---- Forwarded Message ----\n\n' + body;
|
body = '\n\n---- Forwarded Message ----\n\n' + body;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
body = body.split('\n').map(line => '> ' + line).join('\n');
|
body = body.split('\n').map(line => '> ' + line).join('\n');
|
||||||
if (haveSel) {
|
let sig = accountSettings?.Signature || '';
|
||||||
|
if (!accountSettings?.Quoting && haveSel || accountSettings?.Quoting === api.Quoting.Bottom) {
|
||||||
body += '\n\n';
|
body += '\n\n';
|
||||||
|
editOffset = body.length;
|
||||||
|
body += '\n\n' + sig;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let onWroteLine = '';
|
let onWroteLine = '';
|
||||||
|
@ -3091,7 +3155,7 @@ const newMsgView = (miv, msglistView, listMailboxes, possibleLabels, messageLoad
|
||||||
const datetime = mi.Envelope.Date.toLocaleDateString(undefined, { weekday: "short", year: "numeric", month: "short", day: "numeric" }) + ' at ' + mi.Envelope.Date.toLocaleTimeString();
|
const datetime = mi.Envelope.Date.toLocaleDateString(undefined, { weekday: "short", year: "numeric", month: "short", day: "numeric" }) + ' at ' + mi.Envelope.Date.toLocaleTimeString();
|
||||||
onWroteLine = 'On ' + datetime + ', ' + name + ' wrote:\n';
|
onWroteLine = 'On ' + datetime + ', ' + name + ' wrote:\n';
|
||||||
}
|
}
|
||||||
body = '\n\n' + onWroteLine + body;
|
body = '\n\n' + sig + '\n' + onWroteLine + body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const subjectPrefix = forward ? 'Fwd:' : 'Re:';
|
const subjectPrefix = forward ? 'Fwd:' : 'Re:';
|
||||||
|
@ -3108,6 +3172,7 @@ const newMsgView = (miv, msglistView, listMailboxes, possibleLabels, messageLoad
|
||||||
attachmentsMessageItem: forward ? mi : undefined,
|
attachmentsMessageItem: forward ? mi : undefined,
|
||||||
responseMessageID: m.ID,
|
responseMessageID: m.ID,
|
||||||
isList: m.IsMailingList,
|
isList: m.IsMailingList,
|
||||||
|
editOffset: editOffset,
|
||||||
};
|
};
|
||||||
compose(opts);
|
compose(opts);
|
||||||
};
|
};
|
||||||
|
@ -5853,7 +5918,14 @@ const init = async () => {
|
||||||
ensureSearchView();
|
ensureSearchView();
|
||||||
searchView.updateForm();
|
searchView.updateForm();
|
||||||
};
|
};
|
||||||
const cmdCompose = async () => { compose({}); };
|
const cmdCompose = async () => {
|
||||||
|
let body = '';
|
||||||
|
let sig = accountSettings?.Signature || '';
|
||||||
|
if (sig) {
|
||||||
|
body += '\n\n' + sig;
|
||||||
|
}
|
||||||
|
compose({ body: body, editOffset: 0 });
|
||||||
|
};
|
||||||
const cmdOpenInbox = async () => {
|
const cmdOpenInbox = async () => {
|
||||||
const mb = mailboxlistView.findMailboxByName('Inbox');
|
const mb = mailboxlistView.findMailboxByName('Inbox');
|
||||||
if (mb) {
|
if (mb) {
|
||||||
|
@ -5876,6 +5948,7 @@ const init = async () => {
|
||||||
'ctrl ?': cmdTooltip,
|
'ctrl ?': cmdTooltip,
|
||||||
c: cmdCompose,
|
c: cmdCompose,
|
||||||
'ctrl m': cmdFocusMsg,
|
'ctrl m': cmdFocusMsg,
|
||||||
|
'ctrl !': cmdSettings,
|
||||||
};
|
};
|
||||||
const webmailroot = dom.div(style({ display: 'flex', flexDirection: 'column', alignContent: 'stretch', height: '100dvh' }), dom.div(dom._class('topbar'), style({ display: 'flex' }), attr.role('region'), attr.arialabel('Top bar'), topcomposeboxElem = dom.div(dom._class('pad'), style({ width: settings.mailboxesWidth + 'px', textAlign: 'center' }), dom.clickbutton('Compose', attr.title('Compose new email message.'), function click() {
|
const webmailroot = dom.div(style({ display: 'flex', flexDirection: 'column', alignContent: 'stretch', height: '100dvh' }), dom.div(dom._class('topbar'), style({ display: 'flex' }), attr.role('region'), attr.arialabel('Top bar'), topcomposeboxElem = dom.div(dom._class('pad'), style({ width: settings.mailboxesWidth + 'px', textAlign: 'center' }), dom.clickbutton('Compose', attr.title('Compose new email message.'), function click() {
|
||||||
shortcutCmd(cmdCompose, shortcuts);
|
shortcutCmd(cmdCompose, shortcuts);
|
||||||
|
@ -5932,7 +6005,7 @@ const init = async () => {
|
||||||
else {
|
else {
|
||||||
selectLayout(layoutElem.value);
|
selectLayout(layoutElem.value);
|
||||||
}
|
}
|
||||||
}), ' ', dom.clickbutton('Tooltip', attr.title('Show tooltips, based on the title attributes (underdotted text) for the focused element and all user interface elements below it. Use the keyboard shortcut "ctrl ?" instead of clicking on the tooltip button, which changes focus to the tooltip button.'), clickCmd(cmdTooltip, shortcuts)), ' ', dom.clickbutton('Help', attr.title('Show popup with basic usage information and a keyboard shortcuts.'), clickCmd(cmdHelp, shortcuts)), ' ', loginAddressElem = dom.span(), ' ', dom.clickbutton('Logout', attr.title('Logout, invalidating this session.'), async function click(e) {
|
}), ' ', dom.clickbutton('Tooltip', attr.title('Show tooltips, based on the title attributes (underdotted text) for the focused element and all user interface elements below it. Use the keyboard shortcut "ctrl ?" instead of clicking on the tooltip button, which changes focus to the tooltip button.'), clickCmd(cmdTooltip, shortcuts)), ' ', dom.clickbutton('Help', attr.title('Show popup with basic usage information and a keyboard shortcuts.'), clickCmd(cmdHelp, shortcuts)), ' ', dom.clickbutton('Settings', attr.title('Change settings for composing messages.'), clickCmd(cmdSettings, shortcuts)), ' ', loginAddressElem = dom.span(), ' ', dom.clickbutton('Logout', attr.title('Logout, invalidating this session.'), async function click(e) {
|
||||||
await withStatus('Logging out', client.Logout(), e.target);
|
await withStatus('Logging out', client.Logout(), e.target);
|
||||||
localStorageRemove('webmailcsrftoken');
|
localStorageRemove('webmailcsrftoken');
|
||||||
if (eventSource) {
|
if (eventSource) {
|
||||||
|
@ -6329,6 +6402,7 @@ const init = async () => {
|
||||||
lastServerVersion = data.Version;
|
lastServerVersion = data.Version;
|
||||||
const start = checkParse(() => api.parser.EventStart(data));
|
const start = checkParse(() => api.parser.EventStart(data));
|
||||||
log('event start', start);
|
log('event start', start);
|
||||||
|
accountSettings = start.Settings;
|
||||||
connecting = false;
|
connecting = false;
|
||||||
sseID = start.SSEID;
|
sseID = start.SSEID;
|
||||||
loginAddress = start.LoginAddress;
|
loginAddress = start.LoginAddress;
|
||||||
|
|
|
@ -124,6 +124,8 @@ try {
|
||||||
}
|
}
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
|
|
||||||
|
let accountSettings: api.Settings
|
||||||
|
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
showShortcuts: true, // Whether to briefly show shortcuts in bottom left when a button is clicked that has a keyboard shortcut.
|
showShortcuts: true, // Whether to briefly show shortcuts in bottom left when a button is clicked that has a keyboard shortcut.
|
||||||
mailboxesWidth: 240,
|
mailboxesWidth: 240,
|
||||||
|
@ -916,6 +918,19 @@ const withStatus = async <T>(action: string, promise: Promise<T>, disablable?: D
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const withDisabled = async <T>(elem: {disabled: boolean}, p: Promise<T>): Promise<T> => {
|
||||||
|
try {
|
||||||
|
elem.disabled = true
|
||||||
|
return await p
|
||||||
|
} catch (err) {
|
||||||
|
console.log({err})
|
||||||
|
window.alert('Error: ' + errmsg(err))
|
||||||
|
throw err
|
||||||
|
} finally {
|
||||||
|
elem.disabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Popover shows kids in a div on top of a mostly transparent overlay on top of
|
// Popover shows kids in a div on top of a mostly transparent overlay on top of
|
||||||
// the document. If transparent is set, the div the kids are in will not get a
|
// the document. If transparent is set, the div the kids are in will not get a
|
||||||
// white background. If focus is set, it will be called after adding the
|
// white background. If focus is set, it will be called after adding the
|
||||||
|
@ -1045,6 +1060,69 @@ const popup = (...kids: ElemArg[]) => {
|
||||||
return close
|
return close
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show settings screen.
|
||||||
|
const cmdSettings = async () => {
|
||||||
|
let fieldset: HTMLFieldSetElement
|
||||||
|
let signature: HTMLTextAreaElement
|
||||||
|
let quoting: HTMLSelectElement
|
||||||
|
let showAddressSecurity: HTMLInputElement
|
||||||
|
|
||||||
|
if (!accountSettings) {
|
||||||
|
window.alert('No account settings fetched yet.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const remove = popup(
|
||||||
|
style({padding: '1em 1em 2em 1em', minWidth: '30em'}),
|
||||||
|
dom.h1('Settings'),
|
||||||
|
dom.form(
|
||||||
|
async function submit(e: SubmitEvent) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
const accSet: api.Settings = {
|
||||||
|
ID: accountSettings.ID,
|
||||||
|
Signature: signature.value,
|
||||||
|
Quoting: quoting.value as api.Quoting,
|
||||||
|
ShowAddressSecurity: showAddressSecurity.checked,
|
||||||
|
}
|
||||||
|
await withDisabled(fieldset, client.SettingsSave(accSet))
|
||||||
|
accountSettings = accSet
|
||||||
|
remove()
|
||||||
|
},
|
||||||
|
fieldset=dom.fieldset(
|
||||||
|
dom.label(
|
||||||
|
style({margin: '1ex 0', display: 'block'}),
|
||||||
|
dom.div('Signature'),
|
||||||
|
signature=dom.textarea(
|
||||||
|
new String(accountSettings.Signature),
|
||||||
|
style({width: '100%'}),
|
||||||
|
attr.rows(''+Math.max(3, 1+accountSettings.Signature.split('\n').length)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dom.label(
|
||||||
|
style({margin: '1ex 0', display: 'block'}),
|
||||||
|
dom.div('Reply above/below original'),
|
||||||
|
attr.title('Auto: If text is selected, only the replied text is quoted and editing starts below. Otherwise, the full message is quoted and editing starts at the top.'),
|
||||||
|
quoting=dom.select(
|
||||||
|
dom.option(attr.value(''), 'Auto'),
|
||||||
|
dom.option(attr.value('bottom'), 'Bottom', accountSettings.Quoting === api.Quoting.Bottom ? attr.selected('') : []),
|
||||||
|
dom.option(attr.value('top'), 'Top', accountSettings.Quoting === api.Quoting.Top ? attr.selected('') : []),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dom.label(
|
||||||
|
style({margin: '1ex 0', display: 'block'}),
|
||||||
|
showAddressSecurity=dom.input(attr.type('checkbox'), accountSettings.ShowAddressSecurity ? attr.checked('') : []),
|
||||||
|
' Show address security indications',
|
||||||
|
attr.title('Show bars underneath address input fields, indicating support for STARTTLS/DNSSEC/DANE/MTA-STS/RequireTLS.'),
|
||||||
|
),
|
||||||
|
dom.br(),
|
||||||
|
dom.div(
|
||||||
|
dom.submitbutton('Save'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Show help popup, with shortcuts and basic explanation.
|
// Show help popup, with shortcuts and basic explanation.
|
||||||
const cmdHelp = async () => {
|
const cmdHelp = async () => {
|
||||||
const remove = popup(
|
const remove = popup(
|
||||||
|
@ -1271,6 +1349,7 @@ type ComposeOptions = {
|
||||||
responseMessageID?: number
|
responseMessageID?: number
|
||||||
// Whether message is to a list, due to List-Id header.
|
// Whether message is to a list, due to List-Id header.
|
||||||
isList?: boolean
|
isList?: boolean
|
||||||
|
editOffset?: number // For cursor, default at start.
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ComposeView {
|
interface ComposeView {
|
||||||
|
@ -1410,6 +1489,9 @@ const compose = (opts: ComposeOptions) => {
|
||||||
let autosizeElem: HTMLElement, inputElem: HTMLInputElement, securityBar: HTMLElement
|
let autosizeElem: HTMLElement, inputElem: HTMLInputElement, securityBar: HTMLElement
|
||||||
|
|
||||||
const fetchRecipientSecurity = () => {
|
const fetchRecipientSecurity = () => {
|
||||||
|
if (!accountSettings?.ShowAddressSecurity) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (inputElem.value === rcptSecAddr) {
|
if (inputElem.value === rcptSecAddr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1505,7 +1587,7 @@ const compose = (opts: ComposeOptions) => {
|
||||||
style({width: 'auto'}),
|
style({width: 'auto'}),
|
||||||
attr.value(addr),
|
attr.value(addr),
|
||||||
newAddressComplete(),
|
newAddressComplete(),
|
||||||
attr.title(recipientSecurityTitle),
|
accountSettings?.ShowAddressSecurity ? attr.title(recipientSecurityTitle) : [],
|
||||||
function keydown(e: KeyboardEvent) {
|
function keydown(e: KeyboardEvent) {
|
||||||
if (e.key === '-' && e.ctrlKey) {
|
if (e.key === '-' && e.ctrlKey) {
|
||||||
remove()
|
remove()
|
||||||
|
@ -1721,7 +1803,7 @@ const compose = (opts: ComposeOptions) => {
|
||||||
// Explicit string object so it doesn't get the highlight-unicode-block-changes
|
// Explicit string object so it doesn't get the highlight-unicode-block-changes
|
||||||
// treatment, which would cause characters to disappear.
|
// treatment, which would cause characters to disappear.
|
||||||
new String(opts.body || ''),
|
new String(opts.body || ''),
|
||||||
opts.body && !opts.isForward && !opts.body.startsWith('\n\n') ? prop({selectionStart: opts.body.length, selectionEnd: opts.body.length}) : [],
|
prop({selectionStart: opts.editOffset || 0, selectionEnd: opts.editOffset || 0}),
|
||||||
function keyup(e: KeyboardEvent) {
|
function keyup(e: KeyboardEvent) {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
checkAttachments()
|
checkAttachments()
|
||||||
|
@ -2464,12 +2546,16 @@ const newMsgView = (miv: MsgitemView, msglistView: MsglistView, listMailboxes: l
|
||||||
body = pm.Texts[0]
|
body = pm.Texts[0]
|
||||||
}
|
}
|
||||||
body = body.replace(/\r/g, '').replace(/\n\n\n\n*/g, '\n\n').trim()
|
body = body.replace(/\r/g, '').replace(/\n\n\n\n*/g, '\n\n').trim()
|
||||||
|
let editOffset = 0
|
||||||
if (forward) {
|
if (forward) {
|
||||||
body = '\n\n---- Forwarded Message ----\n\n'+body
|
body = '\n\n---- Forwarded Message ----\n\n'+body
|
||||||
} else {
|
} else {
|
||||||
body = body.split('\n').map(line => '> ' + line).join('\n')
|
body = body.split('\n').map(line => '> ' + line).join('\n')
|
||||||
if (haveSel) {
|
let sig = accountSettings?.Signature || ''
|
||||||
|
if (!accountSettings?.Quoting && haveSel || accountSettings?.Quoting === api.Quoting.Bottom) {
|
||||||
body += '\n\n'
|
body += '\n\n'
|
||||||
|
editOffset = body.length
|
||||||
|
body += '\n\n' + sig
|
||||||
} else {
|
} else {
|
||||||
let onWroteLine = ''
|
let onWroteLine = ''
|
||||||
if (mi.Envelope.Date && mi.Envelope.From && mi.Envelope.From.length === 1) {
|
if (mi.Envelope.Date && mi.Envelope.From && mi.Envelope.From.length === 1) {
|
||||||
|
@ -2478,7 +2564,7 @@ const newMsgView = (miv: MsgitemView, msglistView: MsglistView, listMailboxes: l
|
||||||
const datetime = mi.Envelope.Date.toLocaleDateString(undefined, {weekday: "short", year: "numeric", month: "short", day: "numeric"}) + ' at ' + mi.Envelope.Date.toLocaleTimeString()
|
const datetime = mi.Envelope.Date.toLocaleDateString(undefined, {weekday: "short", year: "numeric", month: "short", day: "numeric"}) + ' at ' + mi.Envelope.Date.toLocaleTimeString()
|
||||||
onWroteLine = 'On ' + datetime + ', ' + name + ' wrote:\n'
|
onWroteLine = 'On ' + datetime + ', ' + name + ' wrote:\n'
|
||||||
}
|
}
|
||||||
body = '\n\n' + onWroteLine + body
|
body = '\n\n' + sig + '\n' + onWroteLine + body
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const subjectPrefix = forward ? 'Fwd:' : 'Re:'
|
const subjectPrefix = forward ? 'Fwd:' : 'Re:'
|
||||||
|
@ -2495,6 +2581,7 @@ const newMsgView = (miv: MsgitemView, msglistView: MsglistView, listMailboxes: l
|
||||||
attachmentsMessageItem: forward ? mi : undefined,
|
attachmentsMessageItem: forward ? mi : undefined,
|
||||||
responseMessageID: m.ID,
|
responseMessageID: m.ID,
|
||||||
isList: m.IsMailingList,
|
isList: m.IsMailingList,
|
||||||
|
editOffset: editOffset,
|
||||||
}
|
}
|
||||||
compose(opts)
|
compose(opts)
|
||||||
}
|
}
|
||||||
|
@ -6029,7 +6116,14 @@ const init = async () => {
|
||||||
searchView.updateForm()
|
searchView.updateForm()
|
||||||
}
|
}
|
||||||
|
|
||||||
const cmdCompose = async () => { compose({}) }
|
const cmdCompose = async () => {
|
||||||
|
let body = ''
|
||||||
|
let sig = accountSettings?.Signature || ''
|
||||||
|
if (sig) {
|
||||||
|
body += '\n\n' + sig
|
||||||
|
}
|
||||||
|
compose({body: body, editOffset: 0})
|
||||||
|
}
|
||||||
const cmdOpenInbox = async () => {
|
const cmdOpenInbox = async () => {
|
||||||
const mb = mailboxlistView.findMailboxByName('Inbox')
|
const mb = mailboxlistView.findMailboxByName('Inbox')
|
||||||
if (mb) {
|
if (mb) {
|
||||||
|
@ -6053,6 +6147,7 @@ const init = async () => {
|
||||||
'ctrl ?': cmdTooltip,
|
'ctrl ?': cmdTooltip,
|
||||||
c: cmdCompose,
|
c: cmdCompose,
|
||||||
'ctrl m': cmdFocusMsg,
|
'ctrl m': cmdFocusMsg,
|
||||||
|
'ctrl !': cmdSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
const webmailroot = dom.div(
|
const webmailroot = dom.div(
|
||||||
|
@ -6160,6 +6255,8 @@ const init = async () => {
|
||||||
' ',
|
' ',
|
||||||
dom.clickbutton('Help', attr.title('Show popup with basic usage information and a keyboard shortcuts.'), clickCmd(cmdHelp, shortcuts)),
|
dom.clickbutton('Help', attr.title('Show popup with basic usage information and a keyboard shortcuts.'), clickCmd(cmdHelp, shortcuts)),
|
||||||
' ',
|
' ',
|
||||||
|
dom.clickbutton('Settings', attr.title('Change settings for composing messages.'), clickCmd(cmdSettings, shortcuts)),
|
||||||
|
' ',
|
||||||
loginAddressElem=dom.span(),
|
loginAddressElem=dom.span(),
|
||||||
' ',
|
' ',
|
||||||
dom.clickbutton('Logout', attr.title('Logout, invalidating this session.'), async function click(e: MouseEvent) {
|
dom.clickbutton('Logout', attr.title('Logout, invalidating this session.'), async function click(e: MouseEvent) {
|
||||||
|
@ -6650,6 +6747,7 @@ const init = async () => {
|
||||||
const start = checkParse(() => api.parser.EventStart(data))
|
const start = checkParse(() => api.parser.EventStart(data))
|
||||||
log('event start', start)
|
log('event start', start)
|
||||||
|
|
||||||
|
accountSettings = start.Settings
|
||||||
connecting = false
|
connecting = false
|
||||||
sseID = start.SSEID
|
sseID = start.SSEID
|
||||||
loginAddress = start.LoginAddress
|
loginAddress = start.LoginAddress
|
||||||
|
|
Loading…
Reference in a new issue