mirror of
https://github.com/mjl-/mox.git
synced 2025-04-21 21:40:01 +03:00
imapserver: return all the extensible fields for bodystructure, notably for content-disposition
The gmail iOS/Android app were showing mime image parts as (garbled) text instead of rendering them as image. By returning all the optional fields in the bodystructure fetch attribute, the gmail app renders the image as expected by the user. So we now add all fields. We didn't before, because we weren't keeping track of Content-MD5, Content-Language and Content-Location header fields, since they aren't that useful. Messages in mailboxes have to be reparsed: ./mox reparse Without reparsing, imap responses will claim the extra fields (content-disposition) are absent for existing messages, instead of not claiming anything at all, which is what we did before. Accounts and all/some mailboxes can get their "uid validity" bumped ("./mox bumpuidvalidity $account [$mailbox]"), which should trigger clients to load all messages from scratch, but gmail doesn't appear to notice, so it would be better to remove & add the account in gmail. For issue #327, also relevant to issue #217.
This commit is contained in:
parent
69d2699961
commit
2defbce0bc
11 changed files with 185 additions and 65 deletions
imapserver
message
rfc
store
webmail
|
@ -9,17 +9,18 @@ import (
|
|||
"io"
|
||||
"log/slog"
|
||||
"maps"
|
||||
"mime"
|
||||
"net/textproto"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/mjl-/bstore"
|
||||
|
||||
"github.com/mjl-/mox/message"
|
||||
"github.com/mjl-/mox/mlog"
|
||||
"github.com/mjl-/mox/mox-"
|
||||
"github.com/mjl-/mox/moxio"
|
||||
"github.com/mjl-/mox/store"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// functions to handle fetch attribute requests are defined on fetchCmd.
|
||||
|
@ -483,7 +484,7 @@ func (cmd *fetchCmd) xprocessAtt(a fetchAtt) []token {
|
|||
|
||||
case "BODYSTRUCTURE":
|
||||
_, part := cmd.xensureParsed()
|
||||
bs := xbodystructure(part, true)
|
||||
bs := xbodystructure(cmd.conn.log, part, true)
|
||||
return []token{bare("BODYSTRUCTURE"), bs}
|
||||
|
||||
case "BODY":
|
||||
|
@ -768,7 +769,7 @@ func (cmd *fetchCmd) xbody(a fetchAtt) (string, token) {
|
|||
|
||||
if a.section == nil {
|
||||
// Non-extensible form of BODYSTRUCTURE.
|
||||
return a.field, xbodystructure(part, false)
|
||||
return a.field, xbodystructure(cmd.conn.log, part, false)
|
||||
}
|
||||
|
||||
cmd.peekOrSeen(a.peek)
|
||||
|
@ -939,24 +940,17 @@ func (cmd *fetchCmd) sectionMsgtextName(smt *sectionMsgtext) string {
|
|||
return s
|
||||
}
|
||||
|
||||
func bodyFldParams(params map[string]string) token {
|
||||
if len(params) == 0 {
|
||||
func bodyFldParams(p *message.Part) token {
|
||||
if len(p.ContentTypeParams) == 0 {
|
||||
return nilt
|
||||
}
|
||||
params := make(listspace, 0, 2*len(p.ContentTypeParams))
|
||||
// Ensure same ordering, easier for testing.
|
||||
var keys []string
|
||||
for k := range params {
|
||||
keys = append(keys, k)
|
||||
for _, k := range slices.Sorted(maps.Keys(p.ContentTypeParams)) {
|
||||
v := p.ContentTypeParams[k]
|
||||
params = append(params, string0(strings.ToUpper(k)), string0(v))
|
||||
}
|
||||
sort.Strings(keys)
|
||||
l := make(listspace, 2*len(keys))
|
||||
i := 0
|
||||
for _, k := range keys {
|
||||
l[i] = string0(strings.ToUpper(k))
|
||||
l[i+1] = string0(params[k])
|
||||
i += 2
|
||||
}
|
||||
return l
|
||||
return params
|
||||
}
|
||||
|
||||
func bodyFldEnc(s string) token {
|
||||
|
@ -968,26 +962,80 @@ func bodyFldEnc(s string) token {
|
|||
return string0(s)
|
||||
}
|
||||
|
||||
func bodyFldMd5(p *message.Part) token {
|
||||
if p.ContentMD5 == "" {
|
||||
return nilt
|
||||
}
|
||||
return string0(p.ContentMD5)
|
||||
}
|
||||
|
||||
func bodyFldDisp(log mlog.Log, p *message.Part) token {
|
||||
if p.ContentDisposition == "" {
|
||||
return nilt
|
||||
}
|
||||
|
||||
// ../rfc/9051:5989
|
||||
// mime.ParseMediaType recombines parameter value continuations like "title*0" and
|
||||
// "title*1" into "title". ../rfc/2231:147
|
||||
// And decodes character sets and removes language tags, like
|
||||
// "title*0*=us-ascii'en'hello%20world. ../rfc/2231:210
|
||||
|
||||
disp, params, err := mime.ParseMediaType(p.ContentDisposition)
|
||||
if err != nil {
|
||||
log.Debugx("parsing content-disposition, ignoring", err, slog.String("header", p.ContentDisposition))
|
||||
return nilt
|
||||
} else if len(params) == 0 {
|
||||
log.Debug("content-disposition has no parameters, ignoring", slog.String("header", p.ContentDisposition))
|
||||
return nilt
|
||||
}
|
||||
var fields listspace
|
||||
for _, k := range slices.Sorted(maps.Keys(params)) {
|
||||
fields = append(fields, string0(k), string0(params[k]))
|
||||
}
|
||||
return listspace{string0(disp), fields}
|
||||
}
|
||||
|
||||
func bodyFldLang(p *message.Part) token {
|
||||
// todo: ../rfc/3282:86 ../rfc/5646:218 we currently just split on comma and trim space, should properly parse header.
|
||||
if p.ContentLanguage == "" {
|
||||
return nilt
|
||||
}
|
||||
var l listspace
|
||||
for _, s := range strings.Split(p.ContentLanguage, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return string0(p.ContentLanguage)
|
||||
}
|
||||
l = append(l, string0(s))
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func bodyFldLoc(p *message.Part) token {
|
||||
if p.ContentLocation == "" {
|
||||
return nilt
|
||||
}
|
||||
return string0(p.ContentLocation)
|
||||
}
|
||||
|
||||
// xbodystructure returns a "body".
|
||||
// calls itself for multipart messages and message/{rfc822,global}.
|
||||
func xbodystructure(p *message.Part, extensible bool) token {
|
||||
func xbodystructure(log mlog.Log, p *message.Part, extensible bool) token {
|
||||
if p.MediaType == "MULTIPART" {
|
||||
// Multipart, ../rfc/9051:6355 ../rfc/9051:6411
|
||||
var bodies concat
|
||||
for i := range p.Parts {
|
||||
bodies = append(bodies, xbodystructure(&p.Parts[i], extensible))
|
||||
bodies = append(bodies, xbodystructure(log, &p.Parts[i], extensible))
|
||||
}
|
||||
r := listspace{bodies, string0(p.MediaSubType)}
|
||||
// ../rfc/9051:6371
|
||||
if extensible {
|
||||
if len(p.ContentTypeParams) == 0 {
|
||||
r = append(r, nilt)
|
||||
} else {
|
||||
params := make(listspace, 0, 2*len(p.ContentTypeParams))
|
||||
for k, v := range p.ContentTypeParams {
|
||||
params = append(params, string0(k), string0(v))
|
||||
}
|
||||
r = append(r, params)
|
||||
}
|
||||
r = append(r,
|
||||
bodyFldParams(p),
|
||||
bodyFldDisp(log, p),
|
||||
bodyFldLang(p),
|
||||
bodyFldLoc(p),
|
||||
)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
@ -999,7 +1047,7 @@ func xbodystructure(p *message.Part, extensible bool) token {
|
|||
r = listspace{
|
||||
dquote("TEXT"), string0(p.MediaSubType), // ../rfc/9051:6739
|
||||
// ../rfc/9051:6376
|
||||
bodyFldParams(p.ContentTypeParams), // ../rfc/9051:6401
|
||||
bodyFldParams(p), // ../rfc/9051:6401
|
||||
nilOrString(p.ContentID),
|
||||
nilOrString(p.ContentDescription),
|
||||
bodyFldEnc(p.ContentTransferEncoding),
|
||||
|
@ -1012,13 +1060,13 @@ func xbodystructure(p *message.Part, extensible bool) token {
|
|||
r = listspace{
|
||||
dquote("MESSAGE"), dquote(p.MediaSubType), // ../rfc/9051:6732
|
||||
// ../rfc/9051:6376
|
||||
bodyFldParams(p.ContentTypeParams), // ../rfc/9051:6401
|
||||
bodyFldParams(p), // ../rfc/9051:6401
|
||||
nilOrString(p.ContentID),
|
||||
nilOrString(p.ContentDescription),
|
||||
bodyFldEnc(p.ContentTransferEncoding),
|
||||
number(p.EndOffset - p.BodyOffset),
|
||||
xenvelope(p.Message),
|
||||
xbodystructure(p.Message, extensible),
|
||||
xbodystructure(log, p.Message, extensible),
|
||||
number(p.RawLineCount), // todo: or mp.RawLineCount?
|
||||
}
|
||||
} else {
|
||||
|
@ -1033,13 +1081,21 @@ func xbodystructure(p *message.Part, extensible bool) token {
|
|||
r = listspace{
|
||||
media, string0(p.MediaSubType), // ../rfc/9051:6723
|
||||
// ../rfc/9051:6376
|
||||
bodyFldParams(p.ContentTypeParams), // ../rfc/9051:6401
|
||||
bodyFldParams(p), // ../rfc/9051:6401
|
||||
nilOrString(p.ContentID),
|
||||
nilOrString(p.ContentDescription),
|
||||
bodyFldEnc(p.ContentTransferEncoding),
|
||||
number(p.EndOffset - p.BodyOffset),
|
||||
}
|
||||
}
|
||||
// todo: if "extensible", we could add the value of the "content-md5" header. we don't have it in our parsed data structure, so we don't add it. likely no one would use it, also not any of the other optional fields. ../rfc/9051:6366
|
||||
if extensible {
|
||||
// ../rfc/9051:6366
|
||||
r = append(r,
|
||||
bodyFldMd5(p),
|
||||
bodyFldDisp(log, p),
|
||||
bodyFldLang(p),
|
||||
bodyFldLoc(p),
|
||||
)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
|
|
@ -35,20 +35,23 @@ func TestFetch(t *testing.T) {
|
|||
MessageID: "<B27397-0100000@Blurdybloop.example>",
|
||||
}
|
||||
noflags := imapclient.FetchFlags(nil)
|
||||
bodystructbody1 := imapclient.BodyTypeText{
|
||||
MediaType: "TEXT",
|
||||
MediaSubtype: "PLAIN",
|
||||
BodyFields: imapclient.BodyFields{
|
||||
Params: [][2]string{[...]string{"CHARSET", "US-ASCII"}},
|
||||
Octets: 57,
|
||||
},
|
||||
Lines: 2,
|
||||
}
|
||||
bodyxstructure1 := imapclient.FetchBodystructure{
|
||||
RespAttr: "BODY",
|
||||
Body: imapclient.BodyTypeText{
|
||||
MediaType: "TEXT",
|
||||
MediaSubtype: "PLAIN",
|
||||
BodyFields: imapclient.BodyFields{
|
||||
Params: [][2]string{[...]string{"CHARSET", "US-ASCII"}},
|
||||
Octets: 57,
|
||||
},
|
||||
Lines: 2,
|
||||
},
|
||||
Body: bodystructbody1,
|
||||
}
|
||||
bodystructure1 := bodyxstructure1
|
||||
bodystructure1.RespAttr = "BODYSTRUCTURE"
|
||||
bodystructbody1.Ext = &imapclient.BodyExtension1Part{}
|
||||
bodystructure1.Body = bodystructbody1
|
||||
|
||||
split := strings.SplitN(exampleMsg, "\r\n\r\n", 2)
|
||||
exampleMsgHeader := split[0] + "\r\n\r\n"
|
||||
|
@ -288,17 +291,17 @@ func TestFetch(t *testing.T) {
|
|||
RespAttr: "BODYSTRUCTURE",
|
||||
Body: imapclient.BodyTypeMpart{
|
||||
Bodies: []any{
|
||||
imapclient.BodyTypeBasic{BodyFields: imapclient.BodyFields{Octets: 275}},
|
||||
imapclient.BodyTypeText{MediaType: "TEXT", MediaSubtype: "PLAIN", BodyFields: imapclient.BodyFields{Params: [][2]string{{"CHARSET", "US-ASCII"}}, Octets: 114}, Lines: 3},
|
||||
imapclient.BodyTypeBasic{BodyFields: imapclient.BodyFields{Octets: 275}, Ext: &imapclient.BodyExtension1Part{}},
|
||||
imapclient.BodyTypeText{MediaType: "TEXT", MediaSubtype: "PLAIN", BodyFields: imapclient.BodyFields{Params: [][2]string{{"CHARSET", "US-ASCII"}}, Octets: 114}, Lines: 3, Ext: &imapclient.BodyExtension1Part{}},
|
||||
imapclient.BodyTypeMpart{
|
||||
Bodies: []any{
|
||||
imapclient.BodyTypeBasic{MediaType: "AUDIO", MediaSubtype: "BASIC", BodyFields: imapclient.BodyFields{CTE: "BASE64", Octets: 22}},
|
||||
imapclient.BodyTypeBasic{MediaType: "IMAGE", MediaSubtype: "JPEG", BodyFields: imapclient.BodyFields{CTE: "BASE64"}},
|
||||
imapclient.BodyTypeBasic{MediaType: "AUDIO", MediaSubtype: "BASIC", BodyFields: imapclient.BodyFields{CTE: "BASE64", Octets: 22}, Ext: &imapclient.BodyExtension1Part{}},
|
||||
imapclient.BodyTypeBasic{MediaType: "IMAGE", MediaSubtype: "JPEG", BodyFields: imapclient.BodyFields{CTE: "BASE64"}, Ext: &imapclient.BodyExtension1Part{Disposition: "inline", DispositionParams: [][2]string{{"filename", "image.jpg"}}}},
|
||||
},
|
||||
MediaSubtype: "PARALLEL",
|
||||
Ext: &imapclient.BodyExtensionMpart{Params: [][2]string{{"boundary", "unique-boundary-2"}}},
|
||||
Ext: &imapclient.BodyExtensionMpart{Params: [][2]string{{"BOUNDARY", "unique-boundary-2"}}},
|
||||
},
|
||||
imapclient.BodyTypeText{MediaType: "TEXT", MediaSubtype: "ENRICHED", BodyFields: imapclient.BodyFields{Octets: 145}, Lines: 5},
|
||||
imapclient.BodyTypeText{MediaType: "TEXT", MediaSubtype: "ENRICHED", BodyFields: imapclient.BodyFields{Octets: 145}, Lines: 5, Ext: &imapclient.BodyExtension1Part{}},
|
||||
imapclient.BodyTypeMsg{
|
||||
MediaType: "MESSAGE",
|
||||
MediaSubtype: "RFC822",
|
||||
|
@ -311,12 +314,17 @@ func TestFetch(t *testing.T) {
|
|||
To: []imapclient.Address{{Name: "mox", Adl: "", Mailbox: "info", Host: "mox.example"}},
|
||||
},
|
||||
Bodystructure: imapclient.BodyTypeText{
|
||||
MediaType: "TEXT", MediaSubtype: "PLAIN", BodyFields: imapclient.BodyFields{Params: [][2]string{{"CHARSET", "ISO-8859-1"}}, CTE: "QUOTED-PRINTABLE", Octets: 51}, Lines: 1},
|
||||
MediaType: "TEXT", MediaSubtype: "PLAIN", BodyFields: imapclient.BodyFields{Params: [][2]string{{"CHARSET", "ISO-8859-1"}}, CTE: "QUOTED-PRINTABLE", Octets: 51}, Lines: 1, Ext: &imapclient.BodyExtension1Part{}},
|
||||
Lines: 7,
|
||||
Ext: &imapclient.BodyExtension1Part{
|
||||
MD5: "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=",
|
||||
Language: []string{"en", "de"},
|
||||
Location: "http://localhost",
|
||||
},
|
||||
},
|
||||
},
|
||||
MediaSubtype: "MIXED",
|
||||
Ext: &imapclient.BodyExtensionMpart{Params: [][2]string{{"boundary", "unique-boundary-1"}}},
|
||||
Ext: &imapclient.BodyExtensionMpart{Params: [][2]string{{"BOUNDARY", "unique-boundary-1"}}},
|
||||
},
|
||||
}
|
||||
tc.client.Append("inbox", makeAppendTime(nestedMessage, received))
|
||||
|
@ -390,6 +398,7 @@ aGVsbG8NCndvcmxkDQo=
|
|||
--unique-boundary-2
|
||||
Content-Type: image/jpeg
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: inline; filename=image.jpg
|
||||
|
||||
|
||||
--unique-boundary-2--
|
||||
|
|
|
@ -118,6 +118,7 @@ aGVsbG8NCndvcmxkDQo=
|
|||
--unique-boundary-2
|
||||
Content-Type: image/jpeg
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: inline; filename=image.jpg
|
||||
|
||||
|
||||
--unique-boundary-2--
|
||||
|
@ -133,6 +134,9 @@ Isn't it
|
|||
|
||||
--unique-boundary-1
|
||||
Content-Type: message/rfc822
|
||||
Content-MD5: MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=
|
||||
Content-Language: en,de
|
||||
Content-Location: http://localhost
|
||||
|
||||
From: info@mox.example
|
||||
To: mox <info@mox.example>
|
||||
|
|
|
@ -67,7 +67,11 @@ type Part struct {
|
|||
ContentTypeParams map[string]string // E.g. holds "boundary" for multipart messages. Has lower-case keys, and original case values.
|
||||
ContentID string
|
||||
ContentDescription string
|
||||
ContentTransferEncoding string // In upper case.
|
||||
ContentTransferEncoding string // In upper case.
|
||||
ContentDisposition string
|
||||
ContentMD5 string
|
||||
ContentLanguage string
|
||||
ContentLocation string
|
||||
Envelope *Envelope // Email message headers. Not for non-message parts.
|
||||
|
||||
Parts []Part // Parts if this is a multipart.
|
||||
|
@ -155,6 +159,10 @@ func fallbackPart(p Part, r io.ReaderAt, size int64) (Part, error) {
|
|||
ContentID: p.ContentID,
|
||||
ContentDescription: p.ContentDescription,
|
||||
ContentTransferEncoding: p.ContentTransferEncoding,
|
||||
ContentDisposition: p.ContentDisposition,
|
||||
ContentMD5: p.ContentMD5,
|
||||
ContentLanguage: p.ContentLanguage,
|
||||
ContentLocation: p.ContentLocation,
|
||||
Envelope: p.Envelope,
|
||||
// We don't keep:
|
||||
// - BoundaryOffset: irrelevant for top-level message.
|
||||
|
@ -357,6 +365,10 @@ func newPart(log mlog.Log, strict bool, r io.ReaderAt, offset int64, parent *Par
|
|||
p.ContentID = p.header.Get("Content-Id")
|
||||
p.ContentDescription = p.header.Get("Content-Description")
|
||||
p.ContentTransferEncoding = strings.ToUpper(p.header.Get("Content-Transfer-Encoding"))
|
||||
p.ContentDisposition = p.header.Get("Content-Disposition")
|
||||
p.ContentMD5 = p.header.Get("Content-Md5")
|
||||
p.ContentLanguage = p.header.Get("Content-Language")
|
||||
p.ContentLocation = p.header.Get("Content-Location")
|
||||
|
||||
if parent == nil {
|
||||
p.Envelope, err = parseEnvelope(log, mail.Header(p.header))
|
||||
|
@ -644,13 +656,16 @@ var ErrParamEncoding = errors.New("bad header parameter encoding")
|
|||
// If the returned error is an ErrParamEncoding, it can be treated as a diagnostic
|
||||
// and a filename may still be returned.
|
||||
func (p *Part) DispositionFilename() (disposition string, filename string, err error) {
|
||||
h, err := p.Header()
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("parsing header: %w", err)
|
||||
cd := p.ContentDisposition
|
||||
if cd == "" {
|
||||
h, err := p.Header()
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("parsing header: %w", err)
|
||||
}
|
||||
cd = h.Get("Content-Disposition")
|
||||
}
|
||||
var disp string
|
||||
var params map[string]string
|
||||
cd := h.Get("Content-Disposition")
|
||||
if cd != "" {
|
||||
disp, params, err = mime.ParseMediaType(cd)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ Also see IANA assignments, https://www.iana.org/protocols
|
|||
# Internet Message Format
|
||||
822 Yes Obs Standard for ARPA Internet Text Messages
|
||||
1847 No - Security Multiparts for MIME: Multipart/Signed and Multipart/Encrypted
|
||||
1864 - - The Content-MD5 Header Field
|
||||
2045 Yes - Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
|
||||
2046 Yes - Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types
|
||||
2047 Yes - MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text
|
||||
|
@ -30,12 +31,15 @@ Also see IANA assignments, https://www.iana.org/protocols
|
|||
2076 - - Common Internet Message Headers
|
||||
2183 Yes - Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field
|
||||
2231 Yes - MIME Parameter Value and Encoded Word Extensions: Character Sets, Languages, and Continuations
|
||||
2557 - - MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)
|
||||
3282 - - Content Language Headers
|
||||
3629 - - UTF-8, a transformation format of ISO 10646
|
||||
3676 No - The Text/Plain Format and DelSp Parameters
|
||||
4155 - - The application/mbox Media Type
|
||||
5234 - - Augmented BNF for Syntax Specifications: ABNF
|
||||
5322 Yes - Internet Message Format
|
||||
5598 - - Internet Mail Architecture
|
||||
5646 - - Tags for Identifying Languages
|
||||
6854 - - Update to Internet Message Format to Allow Group Syntax in the "From:" and "Sender:" Header Fields
|
||||
7405 - - Case-Sensitive String Support in ABNF
|
||||
9078 - - Reaction: Indicating Summary Reaction to a Message
|
||||
|
|
|
@ -573,9 +573,9 @@ type Message struct {
|
|||
// want to strip whitespace.
|
||||
Preview *string
|
||||
|
||||
// ParsedBuf message structure. Currently saved as JSON of message.Part because bstore
|
||||
// cannot yet store recursive types. Created when first needed, and saved in the
|
||||
// database.
|
||||
// ParsedBuf message structure. Currently saved as JSON of message.Part because
|
||||
// bstore wasn't able to store recursive types when this was implemented. Created
|
||||
// when first needed, and saved in the database.
|
||||
// todo: once replaced with non-json storage, remove date fixup in ../message/part.go.
|
||||
ParsedBuf []byte
|
||||
}
|
||||
|
|
|
@ -1168,6 +1168,34 @@
|
|||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ContentDisposition",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ContentMD5",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ContentLanguage",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ContentLocation",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Envelope",
|
||||
"Docs": "Email message headers. Not for non-message parts.",
|
||||
|
@ -2641,7 +2669,7 @@
|
|||
},
|
||||
{
|
||||
"Name": "ParsedBuf",
|
||||
"Docs": "ParsedBuf message structure. Currently saved as JSON of message.Part because bstore cannot yet store recursive types. Created when first needed, and saved in the database. todo: once replaced with non-json storage, remove date fixup in ../message/part.go.",
|
||||
"Docs": "ParsedBuf message structure. Currently saved as JSON of message.Part because bstore wasn't able to store recursive types when this was implemented. Created when first needed, and saved in the database. todo: once replaced with non-json storage, remove date fixup in ../message/part.go.",
|
||||
"Typewords": [
|
||||
"[]",
|
||||
"uint8"
|
||||
|
|
|
@ -87,6 +87,10 @@ export interface Part {
|
|||
ContentID: string
|
||||
ContentDescription: string
|
||||
ContentTransferEncoding: string // In upper case.
|
||||
ContentDisposition: string
|
||||
ContentMD5: string
|
||||
ContentLanguage: string
|
||||
ContentLocation: string
|
||||
Envelope?: Envelope | null // Email message headers. Not for non-message parts.
|
||||
Parts?: Part[] | null // Parts if this is a multipart.
|
||||
Message?: Part | null // Only for message/rfc822 and message/global. This part may have a buffer as backing io.ReaderAt, because a message/global can have a non-identity content-transfer-encoding. This part has a nil parent.
|
||||
|
@ -378,7 +382,7 @@ export interface Message {
|
|||
TrainedJunk?: boolean | null // If nil, no training done yet. Otherwise, true is trained as junk, false trained as nonjunk.
|
||||
MsgPrefix?: string | null // Typically holds received headers and/or header separator.
|
||||
Preview?: string | null // If non-nil, a preview of the message based on text and/or html parts of the message. Used in the webmail and IMAP PREVIEW extension. If non-nil, it is empty if no preview could be created, or the message has not textual content or couldn't be parsed. Previews are typically created when delivering a message, but not when importing messages, for speed. Previews are generated on first request (in the webmail, or through the IMAP fetch attribute "PREVIEW" (without "LAZY")), and stored with the message at that time. The preview is at most 256 characters (can be more bytes), with detected quoted text replaced with "[...]". Previews typically end with a newline, callers may want to strip whitespace.
|
||||
ParsedBuf?: string | null // ParsedBuf message structure. Currently saved as JSON of message.Part because bstore cannot yet store recursive types. Created when first needed, and saved in the database. todo: once replaced with non-json storage, remove date fixup in ../message/part.go.
|
||||
ParsedBuf?: string | null // ParsedBuf message structure. Currently saved as JSON of message.Part because bstore wasn't able to store recursive types when this was implemented. Created when first needed, and saved in the database. todo: once replaced with non-json storage, remove date fixup in ../message/part.go.
|
||||
}
|
||||
|
||||
// MessageEnvelope is like message.Envelope, as used in message.Part, but including
|
||||
|
@ -606,7 +610,7 @@ export const types: TypenameMap = {
|
|||
"NotFilter": {"Name":"NotFilter","Docs":"","Fields":[{"Name":"Words","Docs":"","Typewords":["[]","string"]},{"Name":"From","Docs":"","Typewords":["[]","string"]},{"Name":"To","Docs":"","Typewords":["[]","string"]},{"Name":"Subject","Docs":"","Typewords":["[]","string"]},{"Name":"Attachments","Docs":"","Typewords":["AttachmentType"]},{"Name":"Labels","Docs":"","Typewords":["[]","string"]}]},
|
||||
"Page": {"Name":"Page","Docs":"","Fields":[{"Name":"AnchorMessageID","Docs":"","Typewords":["int64"]},{"Name":"Count","Docs":"","Typewords":["int32"]},{"Name":"DestMessageID","Docs":"","Typewords":["int64"]}]},
|
||||
"ParsedMessage": {"Name":"ParsedMessage","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"Part","Docs":"","Typewords":["Part"]},{"Name":"Headers","Docs":"","Typewords":["{}","[]","string"]},{"Name":"ViewMode","Docs":"","Typewords":["ViewMode"]},{"Name":"Texts","Docs":"","Typewords":["[]","string"]},{"Name":"HasHTML","Docs":"","Typewords":["bool"]},{"Name":"ListReplyAddress","Docs":"","Typewords":["nullable","MessageAddress"]},{"Name":"TextPaths","Docs":"","Typewords":["[]","[]","int32"]},{"Name":"HTMLPath","Docs":"","Typewords":["[]","int32"]}]},
|
||||
"Part": {"Name":"Part","Docs":"","Fields":[{"Name":"BoundaryOffset","Docs":"","Typewords":["int64"]},{"Name":"HeaderOffset","Docs":"","Typewords":["int64"]},{"Name":"BodyOffset","Docs":"","Typewords":["int64"]},{"Name":"EndOffset","Docs":"","Typewords":["int64"]},{"Name":"RawLineCount","Docs":"","Typewords":["int64"]},{"Name":"DecodedSize","Docs":"","Typewords":["int64"]},{"Name":"MediaType","Docs":"","Typewords":["string"]},{"Name":"MediaSubType","Docs":"","Typewords":["string"]},{"Name":"ContentTypeParams","Docs":"","Typewords":["{}","string"]},{"Name":"ContentID","Docs":"","Typewords":["string"]},{"Name":"ContentDescription","Docs":"","Typewords":["string"]},{"Name":"ContentTransferEncoding","Docs":"","Typewords":["string"]},{"Name":"Envelope","Docs":"","Typewords":["nullable","Envelope"]},{"Name":"Parts","Docs":"","Typewords":["[]","Part"]},{"Name":"Message","Docs":"","Typewords":["nullable","Part"]}]},
|
||||
"Part": {"Name":"Part","Docs":"","Fields":[{"Name":"BoundaryOffset","Docs":"","Typewords":["int64"]},{"Name":"HeaderOffset","Docs":"","Typewords":["int64"]},{"Name":"BodyOffset","Docs":"","Typewords":["int64"]},{"Name":"EndOffset","Docs":"","Typewords":["int64"]},{"Name":"RawLineCount","Docs":"","Typewords":["int64"]},{"Name":"DecodedSize","Docs":"","Typewords":["int64"]},{"Name":"MediaType","Docs":"","Typewords":["string"]},{"Name":"MediaSubType","Docs":"","Typewords":["string"]},{"Name":"ContentTypeParams","Docs":"","Typewords":["{}","string"]},{"Name":"ContentID","Docs":"","Typewords":["string"]},{"Name":"ContentDescription","Docs":"","Typewords":["string"]},{"Name":"ContentTransferEncoding","Docs":"","Typewords":["string"]},{"Name":"ContentDisposition","Docs":"","Typewords":["string"]},{"Name":"ContentMD5","Docs":"","Typewords":["string"]},{"Name":"ContentLanguage","Docs":"","Typewords":["string"]},{"Name":"ContentLocation","Docs":"","Typewords":["string"]},{"Name":"Envelope","Docs":"","Typewords":["nullable","Envelope"]},{"Name":"Parts","Docs":"","Typewords":["[]","Part"]},{"Name":"Message","Docs":"","Typewords":["nullable","Part"]}]},
|
||||
"Envelope": {"Name":"Envelope","Docs":"","Fields":[{"Name":"Date","Docs":"","Typewords":["timestamp"]},{"Name":"Subject","Docs":"","Typewords":["string"]},{"Name":"From","Docs":"","Typewords":["[]","Address"]},{"Name":"Sender","Docs":"","Typewords":["[]","Address"]},{"Name":"ReplyTo","Docs":"","Typewords":["[]","Address"]},{"Name":"To","Docs":"","Typewords":["[]","Address"]},{"Name":"CC","Docs":"","Typewords":["[]","Address"]},{"Name":"BCC","Docs":"","Typewords":["[]","Address"]},{"Name":"InReplyTo","Docs":"","Typewords":["string"]},{"Name":"MessageID","Docs":"","Typewords":["string"]}]},
|
||||
"Address": {"Name":"Address","Docs":"","Fields":[{"Name":"Name","Docs":"","Typewords":["string"]},{"Name":"User","Docs":"","Typewords":["string"]},{"Name":"Host","Docs":"","Typewords":["string"]}]},
|
||||
"MessageAddress": {"Name":"MessageAddress","Docs":"","Fields":[{"Name":"Name","Docs":"","Typewords":["string"]},{"Name":"User","Docs":"","Typewords":["string"]},{"Name":"Domain","Docs":"","Typewords":["Domain"]}]},
|
||||
|
|
|
@ -299,7 +299,7 @@ var api;
|
|||
"NotFilter": { "Name": "NotFilter", "Docs": "", "Fields": [{ "Name": "Words", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "From", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "To", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Subject", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Attachments", "Docs": "", "Typewords": ["AttachmentType"] }, { "Name": "Labels", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||
"Page": { "Name": "Page", "Docs": "", "Fields": [{ "Name": "AnchorMessageID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Count", "Docs": "", "Typewords": ["int32"] }, { "Name": "DestMessageID", "Docs": "", "Typewords": ["int64"] }] },
|
||||
"ParsedMessage": { "Name": "ParsedMessage", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Part", "Docs": "", "Typewords": ["Part"] }, { "Name": "Headers", "Docs": "", "Typewords": ["{}", "[]", "string"] }, { "Name": "ViewMode", "Docs": "", "Typewords": ["ViewMode"] }, { "Name": "Texts", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "HasHTML", "Docs": "", "Typewords": ["bool"] }, { "Name": "ListReplyAddress", "Docs": "", "Typewords": ["nullable", "MessageAddress"] }, { "Name": "TextPaths", "Docs": "", "Typewords": ["[]", "[]", "int32"] }, { "Name": "HTMLPath", "Docs": "", "Typewords": ["[]", "int32"] }] },
|
||||
"Part": { "Name": "Part", "Docs": "", "Fields": [{ "Name": "BoundaryOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "HeaderOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "BodyOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "EndOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "RawLineCount", "Docs": "", "Typewords": ["int64"] }, { "Name": "DecodedSize", "Docs": "", "Typewords": ["int64"] }, { "Name": "MediaType", "Docs": "", "Typewords": ["string"] }, { "Name": "MediaSubType", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTypeParams", "Docs": "", "Typewords": ["{}", "string"] }, { "Name": "ContentID", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentDescription", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTransferEncoding", "Docs": "", "Typewords": ["string"] }, { "Name": "Envelope", "Docs": "", "Typewords": ["nullable", "Envelope"] }, { "Name": "Parts", "Docs": "", "Typewords": ["[]", "Part"] }, { "Name": "Message", "Docs": "", "Typewords": ["nullable", "Part"] }] },
|
||||
"Part": { "Name": "Part", "Docs": "", "Fields": [{ "Name": "BoundaryOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "HeaderOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "BodyOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "EndOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "RawLineCount", "Docs": "", "Typewords": ["int64"] }, { "Name": "DecodedSize", "Docs": "", "Typewords": ["int64"] }, { "Name": "MediaType", "Docs": "", "Typewords": ["string"] }, { "Name": "MediaSubType", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTypeParams", "Docs": "", "Typewords": ["{}", "string"] }, { "Name": "ContentID", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentDescription", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTransferEncoding", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentDisposition", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentMD5", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentLanguage", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentLocation", "Docs": "", "Typewords": ["string"] }, { "Name": "Envelope", "Docs": "", "Typewords": ["nullable", "Envelope"] }, { "Name": "Parts", "Docs": "", "Typewords": ["[]", "Part"] }, { "Name": "Message", "Docs": "", "Typewords": ["nullable", "Part"] }] },
|
||||
"Envelope": { "Name": "Envelope", "Docs": "", "Fields": [{ "Name": "Date", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Subject", "Docs": "", "Typewords": ["string"] }, { "Name": "From", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "Sender", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "ReplyTo", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "To", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "CC", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "BCC", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "InReplyTo", "Docs": "", "Typewords": ["string"] }, { "Name": "MessageID", "Docs": "", "Typewords": ["string"] }] },
|
||||
"Address": { "Name": "Address", "Docs": "", "Fields": [{ "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "User", "Docs": "", "Typewords": ["string"] }, { "Name": "Host", "Docs": "", "Typewords": ["string"] }] },
|
||||
"MessageAddress": { "Name": "MessageAddress", "Docs": "", "Fields": [{ "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "User", "Docs": "", "Typewords": ["string"] }, { "Name": "Domain", "Docs": "", "Typewords": ["Domain"] }] },
|
||||
|
|
|
@ -299,7 +299,7 @@ var api;
|
|||
"NotFilter": { "Name": "NotFilter", "Docs": "", "Fields": [{ "Name": "Words", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "From", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "To", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Subject", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Attachments", "Docs": "", "Typewords": ["AttachmentType"] }, { "Name": "Labels", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||
"Page": { "Name": "Page", "Docs": "", "Fields": [{ "Name": "AnchorMessageID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Count", "Docs": "", "Typewords": ["int32"] }, { "Name": "DestMessageID", "Docs": "", "Typewords": ["int64"] }] },
|
||||
"ParsedMessage": { "Name": "ParsedMessage", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Part", "Docs": "", "Typewords": ["Part"] }, { "Name": "Headers", "Docs": "", "Typewords": ["{}", "[]", "string"] }, { "Name": "ViewMode", "Docs": "", "Typewords": ["ViewMode"] }, { "Name": "Texts", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "HasHTML", "Docs": "", "Typewords": ["bool"] }, { "Name": "ListReplyAddress", "Docs": "", "Typewords": ["nullable", "MessageAddress"] }, { "Name": "TextPaths", "Docs": "", "Typewords": ["[]", "[]", "int32"] }, { "Name": "HTMLPath", "Docs": "", "Typewords": ["[]", "int32"] }] },
|
||||
"Part": { "Name": "Part", "Docs": "", "Fields": [{ "Name": "BoundaryOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "HeaderOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "BodyOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "EndOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "RawLineCount", "Docs": "", "Typewords": ["int64"] }, { "Name": "DecodedSize", "Docs": "", "Typewords": ["int64"] }, { "Name": "MediaType", "Docs": "", "Typewords": ["string"] }, { "Name": "MediaSubType", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTypeParams", "Docs": "", "Typewords": ["{}", "string"] }, { "Name": "ContentID", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentDescription", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTransferEncoding", "Docs": "", "Typewords": ["string"] }, { "Name": "Envelope", "Docs": "", "Typewords": ["nullable", "Envelope"] }, { "Name": "Parts", "Docs": "", "Typewords": ["[]", "Part"] }, { "Name": "Message", "Docs": "", "Typewords": ["nullable", "Part"] }] },
|
||||
"Part": { "Name": "Part", "Docs": "", "Fields": [{ "Name": "BoundaryOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "HeaderOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "BodyOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "EndOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "RawLineCount", "Docs": "", "Typewords": ["int64"] }, { "Name": "DecodedSize", "Docs": "", "Typewords": ["int64"] }, { "Name": "MediaType", "Docs": "", "Typewords": ["string"] }, { "Name": "MediaSubType", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTypeParams", "Docs": "", "Typewords": ["{}", "string"] }, { "Name": "ContentID", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentDescription", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTransferEncoding", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentDisposition", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentMD5", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentLanguage", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentLocation", "Docs": "", "Typewords": ["string"] }, { "Name": "Envelope", "Docs": "", "Typewords": ["nullable", "Envelope"] }, { "Name": "Parts", "Docs": "", "Typewords": ["[]", "Part"] }, { "Name": "Message", "Docs": "", "Typewords": ["nullable", "Part"] }] },
|
||||
"Envelope": { "Name": "Envelope", "Docs": "", "Fields": [{ "Name": "Date", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Subject", "Docs": "", "Typewords": ["string"] }, { "Name": "From", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "Sender", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "ReplyTo", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "To", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "CC", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "BCC", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "InReplyTo", "Docs": "", "Typewords": ["string"] }, { "Name": "MessageID", "Docs": "", "Typewords": ["string"] }] },
|
||||
"Address": { "Name": "Address", "Docs": "", "Fields": [{ "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "User", "Docs": "", "Typewords": ["string"] }, { "Name": "Host", "Docs": "", "Typewords": ["string"] }] },
|
||||
"MessageAddress": { "Name": "MessageAddress", "Docs": "", "Fields": [{ "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "User", "Docs": "", "Typewords": ["string"] }, { "Name": "Domain", "Docs": "", "Typewords": ["Domain"] }] },
|
||||
|
|
|
@ -299,7 +299,7 @@ var api;
|
|||
"NotFilter": { "Name": "NotFilter", "Docs": "", "Fields": [{ "Name": "Words", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "From", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "To", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Subject", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Attachments", "Docs": "", "Typewords": ["AttachmentType"] }, { "Name": "Labels", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||
"Page": { "Name": "Page", "Docs": "", "Fields": [{ "Name": "AnchorMessageID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Count", "Docs": "", "Typewords": ["int32"] }, { "Name": "DestMessageID", "Docs": "", "Typewords": ["int64"] }] },
|
||||
"ParsedMessage": { "Name": "ParsedMessage", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Part", "Docs": "", "Typewords": ["Part"] }, { "Name": "Headers", "Docs": "", "Typewords": ["{}", "[]", "string"] }, { "Name": "ViewMode", "Docs": "", "Typewords": ["ViewMode"] }, { "Name": "Texts", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "HasHTML", "Docs": "", "Typewords": ["bool"] }, { "Name": "ListReplyAddress", "Docs": "", "Typewords": ["nullable", "MessageAddress"] }, { "Name": "TextPaths", "Docs": "", "Typewords": ["[]", "[]", "int32"] }, { "Name": "HTMLPath", "Docs": "", "Typewords": ["[]", "int32"] }] },
|
||||
"Part": { "Name": "Part", "Docs": "", "Fields": [{ "Name": "BoundaryOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "HeaderOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "BodyOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "EndOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "RawLineCount", "Docs": "", "Typewords": ["int64"] }, { "Name": "DecodedSize", "Docs": "", "Typewords": ["int64"] }, { "Name": "MediaType", "Docs": "", "Typewords": ["string"] }, { "Name": "MediaSubType", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTypeParams", "Docs": "", "Typewords": ["{}", "string"] }, { "Name": "ContentID", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentDescription", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTransferEncoding", "Docs": "", "Typewords": ["string"] }, { "Name": "Envelope", "Docs": "", "Typewords": ["nullable", "Envelope"] }, { "Name": "Parts", "Docs": "", "Typewords": ["[]", "Part"] }, { "Name": "Message", "Docs": "", "Typewords": ["nullable", "Part"] }] },
|
||||
"Part": { "Name": "Part", "Docs": "", "Fields": [{ "Name": "BoundaryOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "HeaderOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "BodyOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "EndOffset", "Docs": "", "Typewords": ["int64"] }, { "Name": "RawLineCount", "Docs": "", "Typewords": ["int64"] }, { "Name": "DecodedSize", "Docs": "", "Typewords": ["int64"] }, { "Name": "MediaType", "Docs": "", "Typewords": ["string"] }, { "Name": "MediaSubType", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTypeParams", "Docs": "", "Typewords": ["{}", "string"] }, { "Name": "ContentID", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentDescription", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentTransferEncoding", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentDisposition", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentMD5", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentLanguage", "Docs": "", "Typewords": ["string"] }, { "Name": "ContentLocation", "Docs": "", "Typewords": ["string"] }, { "Name": "Envelope", "Docs": "", "Typewords": ["nullable", "Envelope"] }, { "Name": "Parts", "Docs": "", "Typewords": ["[]", "Part"] }, { "Name": "Message", "Docs": "", "Typewords": ["nullable", "Part"] }] },
|
||||
"Envelope": { "Name": "Envelope", "Docs": "", "Fields": [{ "Name": "Date", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Subject", "Docs": "", "Typewords": ["string"] }, { "Name": "From", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "Sender", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "ReplyTo", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "To", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "CC", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "BCC", "Docs": "", "Typewords": ["[]", "Address"] }, { "Name": "InReplyTo", "Docs": "", "Typewords": ["string"] }, { "Name": "MessageID", "Docs": "", "Typewords": ["string"] }] },
|
||||
"Address": { "Name": "Address", "Docs": "", "Fields": [{ "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "User", "Docs": "", "Typewords": ["string"] }, { "Name": "Host", "Docs": "", "Typewords": ["string"] }] },
|
||||
"MessageAddress": { "Name": "MessageAddress", "Docs": "", "Fields": [{ "Name": "Name", "Docs": "", "Typewords": ["string"] }, { "Name": "User", "Docs": "", "Typewords": ["string"] }, { "Name": "Domain", "Docs": "", "Typewords": ["Domain"] }] },
|
||||
|
|
Loading…
Reference in a new issue