106
108
return textproto.MIMEHeader(h).Get(key)
109
var ErrHeaderNotPresent = os.ErrorString("mail: header not in message")
111
var ErrHeaderNotPresent = os.NewError("mail: header not in message")
111
113
// Date parses the Date header field.
112
114
func (h Header) Date() (*time.Time, os.Error) {
213
215
debug.Printf("parseAddress: %q", *p)
216
return nil, os.ErrorString("mail: no address")
218
return nil, os.NewError("mail: no address")
219
221
// address = name-addr / addr-spec
244
246
// angle-addr = "<" addr-spec ">"
246
248
if !p.consume('<') {
247
return nil, os.ErrorString("mail: no angle-addr")
249
return nil, os.NewError("mail: no angle-addr")
249
251
spec, err = p.consumeAddrSpec()
253
255
if !p.consume('>') {
254
return nil, os.ErrorString("mail: unclosed angle-addr")
256
return nil, os.NewError("mail: unclosed angle-addr")
256
258
debug.Printf("parseAddress: spec=%q", spec)
295
297
if !p.consume('@') {
296
return "", os.ErrorString("mail: missing @ in addr-spec")
298
return "", os.NewError("mail: missing @ in addr-spec")
299
301
// domain = dot-atom / domain-literal
300
302
var domain string
303
return "", os.ErrorString("mail: no domain in addr-spec")
305
return "", os.NewError("mail: no domain in addr-spec")
305
307
// TODO(dsymonds): Handle domain-literal
306
308
domain, err = p.consumeAtom(true)
345
347
// Ignore any error if we got at least one word.
346
348
if err != nil && len(words) == 0 {
347
349
debug.Printf("consumePhrase: hit err: %v", err)
348
return "", os.ErrorString("mail: missing word in phrase")
350
return "", os.NewError("mail: missing word in phrase")
350
352
phrase = strings.Join(words, " ")
351
353
return phrase, nil
361
363
if i >= p.len() {
362
return "", os.ErrorString("mail: unclosed quoted-string")
364
return "", os.NewError("mail: unclosed quoted-string")
364
366
switch c := (*p)[i]; {
368
370
if i+1 == p.len() {
369
return "", os.ErrorString("mail: unclosed quoted-string")
371
return "", os.NewError("mail: unclosed quoted-string")
371
373
qsb = append(qsb, (*p)[i+1])
387
389
// If dot is true, consumeAtom parses an RFC 5322 dot-atom instead.
388
390
func (p *addrParser) consumeAtom(dot bool) (atom string, err os.Error) {
389
391
if !isAtext(p.peek(), false) {
390
return "", os.ErrorString("mail: invalid string")
392
return "", os.NewError("mail: invalid string")
393
395
for ; i < p.len() && isAtext((*p)[i], dot); i++ {
425
427
func decodeRFC2047Word(s string) (string, os.Error) {
426
fields := strings.Split(s, "?", -1)
428
fields := strings.Split(s, "?")
427
429
if len(fields) != 5 || fields[0] != "=" || fields[4] != "=" {
428
return "", os.ErrorString("mail: address not RFC 2047 encoded")
430
return "", os.NewError("mail: address not RFC 2047 encoded")
430
432
charset, enc := strings.ToLower(fields[1]), strings.ToLower(fields[2])
431
// TODO(dsymonds): Support "b" encoding too.
433
return "", fmt.Errorf("mail: RFC 2047 encoding not supported: %q", enc)
435
433
if charset != "iso-8859-1" && charset != "utf-8" {
436
434
return "", fmt.Errorf("mail: charset not supported: %q", charset)
440
b := new(bytes.Buffer)
441
for i := 0; i < len(in); i++ {
443
case c == '=' && i+2 < len(in):
444
x, err := strconv.Btoi64(in[i+1:i+3], 16)
446
return "", fmt.Errorf("mail: invalid RFC 2047 encoding: %q", in[i:i+3])
461
return b.String(), nil
437
in := bytes.NewBufferString(fields[3])
441
r = base64.NewDecoder(base64.StdEncoding, in)
445
return "", fmt.Errorf("mail: RFC 2047 encoding not supported: %q", enc)
448
dec, err := ioutil.ReadAll(r)
455
b := new(bytes.Buffer)
456
for _, c := range dec {
459
return b.String(), nil
461
return string(dec), nil
466
type qDecoder struct {
471
func (qd qDecoder) Read(p []byte) (n int, err os.Error) {
472
// This method writes at most one byte into p.
476
if _, err := qd.r.Read(qd.scratch[:1]); err != nil {
479
switch c := qd.scratch[0]; {
481
if _, err := io.ReadFull(qd.r, qd.scratch[:2]); err != nil {
484
x, err := strconv.Btoi64(string(qd.scratch[:2]), 16)
486
return 0, fmt.Errorf("mail: invalid RFC 2047 encoding: %q", qd.scratch[:2])
464
497
var atextChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ" +