mirror of
https://github.com/mjl-/mox.git
synced 2025-06-27 21:48:16 +03:00
message: when parsing a message, don't treat absent header and empty header value the same
We now use "*string" for such header fields, for Content-* fields, as used in the imapserver when responding to FETCH commands. We'll now return NIL for an absent header, and "" (empty string) if the header value is empty.
This commit is contained in:
parent
3fe765dce9
commit
07533252b3
@ -0,0 +1,7 @@
|
||||
Below are the incompatible changes between v0.0.14 and next, per package.
|
||||
|
||||
# message
|
||||
- Part.ContentDescription: changed from string to *string
|
||||
- Part.ContentID: changed from string to *string
|
||||
- Part.ContentTransferEncoding: changed from string to *string
|
||||
|
@ -50,8 +50,8 @@ func tcheckType(t *testing.T, p *message.Part, mt, mst, cte string) {
|
||||
if !strings.EqualFold(p.MediaSubType, mst) {
|
||||
t.Fatalf("got mediasubtype %q, expected %q", p.MediaSubType, mst)
|
||||
}
|
||||
if !strings.EqualFold(p.ContentTransferEncoding, cte) {
|
||||
t.Fatalf("got content-transfer-encoding %q, expected %q", p.ContentTransferEncoding, cte)
|
||||
if !(cte == "" && p.ContentTransferEncoding == nil || cte != "" && p.ContentTransferEncoding != nil && strings.EqualFold(cte, *p.ContentTransferEncoding)) {
|
||||
t.Fatalf("got content-transfer-encoding %v, expected %v", p.ContentTransferEncoding, cte)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -776,11 +776,15 @@ func (cmd *fetchCmd) xbinary(a fetchAtt) (string, token) {
|
||||
cmd.xerrorf("binary only allowed on leaf parts, not multipart/* or message/rfc822 or message/global")
|
||||
}
|
||||
|
||||
switch p.ContentTransferEncoding {
|
||||
var cte string
|
||||
if p.ContentTransferEncoding != nil {
|
||||
cte = *p.ContentTransferEncoding
|
||||
}
|
||||
switch cte {
|
||||
case "", "7BIT", "8BIT", "BINARY", "BASE64", "QUOTED-PRINTABLE":
|
||||
default:
|
||||
// ../rfc/9051:5913
|
||||
xusercodeErrorf("UNKNOWN-CTE", "unknown Content-Transfer-Encoding %q", p.ContentTransferEncoding)
|
||||
xusercodeErrorf("UNKNOWN-CTE", "unknown Content-Transfer-Encoding %q", cte)
|
||||
}
|
||||
|
||||
r := p.Reader()
|
||||
@ -992,7 +996,11 @@ func bodyFldParams(p *message.Part) token {
|
||||
return params
|
||||
}
|
||||
|
||||
func bodyFldEnc(s string) token {
|
||||
func bodyFldEnc(cte *string) token {
|
||||
var s string
|
||||
if cte != nil {
|
||||
s = *cte
|
||||
}
|
||||
up := strings.ToUpper(s)
|
||||
switch up {
|
||||
case "7BIT", "8BIT", "BINARY", "BASE64", "QUOTED-PRINTABLE":
|
||||
@ -1002,14 +1010,14 @@ func bodyFldEnc(s string) token {
|
||||
}
|
||||
|
||||
func bodyFldMd5(p *message.Part) token {
|
||||
if p.ContentMD5 == "" {
|
||||
if p.ContentMD5 == nil {
|
||||
return nilt
|
||||
}
|
||||
return string0(p.ContentMD5)
|
||||
return string0(*p.ContentMD5)
|
||||
}
|
||||
|
||||
func bodyFldDisp(log mlog.Log, p *message.Part) token {
|
||||
if p.ContentDisposition == "" {
|
||||
if p.ContentDisposition == nil {
|
||||
return nilt
|
||||
}
|
||||
|
||||
@ -1019,12 +1027,12 @@ func bodyFldDisp(log mlog.Log, p *message.Part) token {
|
||||
// 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)
|
||||
disp, params, err := mime.ParseMediaType(*p.ContentDisposition)
|
||||
if err != nil {
|
||||
log.Debugx("parsing content-disposition, ignoring", err, slog.String("header", p.ContentDisposition))
|
||||
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))
|
||||
log.Debug("content-disposition has no parameters, ignoring", slog.String("header", *p.ContentDisposition))
|
||||
return nilt
|
||||
}
|
||||
var fields listspace
|
||||
@ -1036,14 +1044,14 @@ func bodyFldDisp(log mlog.Log, p *message.Part) token {
|
||||
|
||||
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 == "" {
|
||||
if p.ContentLanguage == nil {
|
||||
return nilt
|
||||
}
|
||||
var l listspace
|
||||
for _, s := range strings.Split(p.ContentLanguage, ",") {
|
||||
for _, s := range strings.Split(*p.ContentLanguage, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return string0(p.ContentLanguage)
|
||||
return string0(*p.ContentLanguage)
|
||||
}
|
||||
l = append(l, string0(s))
|
||||
}
|
||||
@ -1051,10 +1059,10 @@ func bodyFldLang(p *message.Part) token {
|
||||
}
|
||||
|
||||
func bodyFldLoc(p *message.Part) token {
|
||||
if p.ContentLocation == "" {
|
||||
if p.ContentLocation == nil {
|
||||
return nilt
|
||||
}
|
||||
return string0(p.ContentLocation)
|
||||
return string0(*p.ContentLocation)
|
||||
}
|
||||
|
||||
// xbodystructure returns a "body".
|
||||
|
@ -34,11 +34,11 @@ func (t niltoken) xwriteTo(c *conn, xw io.Writer) {
|
||||
xw.Write([]byte(t.pack(c)))
|
||||
}
|
||||
|
||||
func nilOrString(s string) token {
|
||||
if s == "" {
|
||||
func nilOrString(s *string) token {
|
||||
if s == nil {
|
||||
return nilt
|
||||
}
|
||||
return string0(s)
|
||||
return string0(*s)
|
||||
}
|
||||
|
||||
type string0 string
|
||||
|
@ -65,14 +65,14 @@ type Part struct {
|
||||
MediaType string // From Content-Type, upper case. E.g. "TEXT". Can be empty because content-type may be absent. In this case, the part may be treated as TEXT/PLAIN.
|
||||
MediaSubType string // From Content-Type, upper case. E.g. "PLAIN".
|
||||
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.
|
||||
ContentDisposition string
|
||||
ContentMD5 string
|
||||
ContentLanguage string
|
||||
ContentLocation string
|
||||
Envelope *Envelope // Email message headers. Not for non-message parts.
|
||||
ContentID *string `json:",omitempty"`
|
||||
ContentDescription *string `json:",omitempty"`
|
||||
ContentTransferEncoding *string `json:",omitempty"` // In upper case.
|
||||
ContentDisposition *string `json:",omitempty"`
|
||||
ContentMD5 *string `json:",omitempty"`
|
||||
ContentLanguage *string `json:",omitempty"`
|
||||
ContentLocation *string `json:",omitempty"`
|
||||
Envelope *Envelope `json:",omitempty"` // Email message headers. Not for non-message parts.
|
||||
|
||||
Parts []Part // Parts if this is a multipart.
|
||||
|
||||
@ -362,13 +362,18 @@ 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")
|
||||
p.ContentID = p.headerGet("Content-Id")
|
||||
p.ContentDescription = p.headerGet("Content-Description")
|
||||
cte := p.headerGet("Content-Transfer-Encoding")
|
||||
if cte != nil {
|
||||
s := strings.ToUpper(*cte)
|
||||
cte = &s
|
||||
}
|
||||
p.ContentTransferEncoding = cte
|
||||
p.ContentDisposition = p.headerGet("Content-Disposition")
|
||||
p.ContentMD5 = p.headerGet("Content-Md5")
|
||||
p.ContentLanguage = p.headerGet("Content-Language")
|
||||
p.ContentLocation = p.headerGet("Content-Location")
|
||||
|
||||
if parent == nil {
|
||||
p.Envelope, err = parseEnvelope(log, mail.Header(p.header))
|
||||
@ -424,6 +429,15 @@ func (p *Part) Header() (textproto.MIMEHeader, error) {
|
||||
return h, err
|
||||
}
|
||||
|
||||
func (p *Part) headerGet(k string) *string {
|
||||
l := p.header.Values(k)
|
||||
if len(l) == 0 {
|
||||
return nil
|
||||
}
|
||||
s := l[0]
|
||||
return &s
|
||||
}
|
||||
|
||||
// HeaderReader returns a reader for the header section of this part, including ending bare CRLF.
|
||||
func (p *Part) HeaderReader() io.Reader {
|
||||
return io.NewSectionReader(p.r, p.HeaderOffset, p.BodyOffset-p.HeaderOffset)
|
||||
@ -657,17 +671,10 @@ var ErrParamEncoding = errors.New("bad header parameter encoding")
|
||||
// and a filename may still be returned.
|
||||
func (p *Part) DispositionFilename() (disposition string, filename string, err error) {
|
||||
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
|
||||
if cd != "" {
|
||||
disp, params, err = mime.ParseMediaType(cd)
|
||||
if cd != nil && *cd != "" {
|
||||
disp, params, err = mime.ParseMediaType(*cd)
|
||||
}
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("%w: parsing disposition header: %v", ErrParamEncoding, err)
|
||||
@ -786,9 +793,13 @@ func (tr *textReader) Read(buf []byte) (int, error) {
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func newDecoder(cte string, r io.Reader) io.Reader {
|
||||
func newDecoder(cte *string, r io.Reader) io.Reader {
|
||||
var s string
|
||||
if cte != nil {
|
||||
s = *cte
|
||||
}
|
||||
// ../rfc/2045:775
|
||||
switch cte {
|
||||
switch s {
|
||||
case "BASE64":
|
||||
return base64.NewDecoder(base64.StdEncoding, r)
|
||||
case "QUOTED-PRINTABLE":
|
||||
|
@ -929,10 +929,14 @@ func PartStructure(log mlog.Log, p *message.Part) (webhook.Structure, error) {
|
||||
} else if err != nil {
|
||||
return webhook.Structure{}, err
|
||||
}
|
||||
var cid string
|
||||
if p.ContentID != nil {
|
||||
cid = *p.ContentID
|
||||
}
|
||||
s := webhook.Structure{
|
||||
ContentType: strings.ToLower(p.MediaType + "/" + p.MediaSubType),
|
||||
ContentTypeParams: p.ContentTypeParams,
|
||||
ContentID: p.ContentID,
|
||||
ContentID: cid,
|
||||
ContentDisposition: strings.ToLower(disp),
|
||||
Filename: filename,
|
||||
DecodedSize: p.DecodedSize,
|
||||
|
@ -1151,6 +1151,7 @@
|
||||
"Name": "ContentID",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"nullable",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
@ -1158,6 +1159,7 @@
|
||||
"Name": "ContentDescription",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"nullable",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
@ -1165,6 +1167,7 @@
|
||||
"Name": "ContentTransferEncoding",
|
||||
"Docs": "In upper case.",
|
||||
"Typewords": [
|
||||
"nullable",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
@ -1172,6 +1175,7 @@
|
||||
"Name": "ContentDisposition",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"nullable",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
@ -1179,6 +1183,7 @@
|
||||
"Name": "ContentMD5",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"nullable",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
@ -1186,6 +1191,7 @@
|
||||
"Name": "ContentLanguage",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"nullable",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
@ -1193,6 +1199,7 @@
|
||||
"Name": "ContentLocation",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"nullable",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
|
@ -84,13 +84,13 @@ export interface Part {
|
||||
MediaType: string // From Content-Type, upper case. E.g. "TEXT". Can be empty because content-type may be absent. In this case, the part may be treated as TEXT/PLAIN.
|
||||
MediaSubType: string // From Content-Type, upper case. E.g. "PLAIN".
|
||||
ContentTypeParams?: { [key: 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.
|
||||
ContentDisposition: string
|
||||
ContentMD5: string
|
||||
ContentLanguage: string
|
||||
ContentLocation: string
|
||||
ContentID?: string | null
|
||||
ContentDescription?: string | null
|
||||
ContentTransferEncoding?: string | null // In upper case.
|
||||
ContentDisposition?: string | null
|
||||
ContentMD5?: string | null
|
||||
ContentLanguage?: string | null
|
||||
ContentLocation?: string | null
|
||||
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.
|
||||
@ -617,7 +617,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":"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"]}]},
|
||||
"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":["nullable","string"]},{"Name":"ContentDescription","Docs":"","Typewords":["nullable","string"]},{"Name":"ContentTransferEncoding","Docs":"","Typewords":["nullable","string"]},{"Name":"ContentDisposition","Docs":"","Typewords":["nullable","string"]},{"Name":"ContentMD5","Docs":"","Typewords":["nullable","string"]},{"Name":"ContentLanguage","Docs":"","Typewords":["nullable","string"]},{"Name":"ContentLocation","Docs":"","Typewords":["nullable","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": "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"] }] },
|
||||
"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": ["nullable", "string"] }, { "Name": "ContentDescription", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentTransferEncoding", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentDisposition", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentMD5", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentLanguage", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentLocation", "Docs": "", "Typewords": ["nullable", "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": "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"] }] },
|
||||
"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": ["nullable", "string"] }, { "Name": "ContentDescription", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentTransferEncoding", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentDisposition", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentMD5", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentLanguage", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentLocation", "Docs": "", "Typewords": ["nullable", "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"] }] },
|
||||
|
@ -898,7 +898,7 @@ func inlineSanitizeHTML(log mlog.Log, setHeaders func(), w io.Writer, p *message
|
||||
func findCID(p *message.Part, parents []*message.Part, cid string) *message.Part {
|
||||
for i := len(parents) - 1; i >= 0; i-- {
|
||||
for j, pp := range parents[i].Parts {
|
||||
if strings.EqualFold(pp.ContentID, cid) {
|
||||
if pp.ContentID != nil && strings.EqualFold(*pp.ContentID, cid) {
|
||||
return &parents[i].Parts[j]
|
||||
}
|
||||
}
|
||||
@ -911,7 +911,7 @@ func findCID(p *message.Part, parents []*message.Part, cid string) *message.Part
|
||||
}
|
||||
|
||||
func findCIDAll(p *message.Part, cid string) *message.Part {
|
||||
if strings.EqualFold(p.ContentID, cid) {
|
||||
if p.ContentID != nil && strings.EqualFold(*p.ContentID, cid) {
|
||||
return p
|
||||
}
|
||||
for i := range p.Parts {
|
||||
|
@ -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": "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"] }] },
|
||||
"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": ["nullable", "string"] }, { "Name": "ContentDescription", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentTransferEncoding", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentDisposition", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentMD5", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentLanguage", "Docs": "", "Typewords": ["nullable", "string"] }, { "Name": "ContentLocation", "Docs": "", "Typewords": ["nullable", "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…
x
Reference in New Issue
Block a user