github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/net/mail/message_test.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package mail
     6  
     7  import (
     8  	"bytes"
     9  	"io/ioutil"
    10  	"reflect"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  )
    15  
    16  var parseTests = []struct {
    17  	in     string
    18  	header Header
    19  	body   string
    20  }{
    21  	{
    22  		// RFC 5322, Appendix A.1.1
    23  		in: `From: John Doe <jdoe@machine.example>
    24  To: Mary Smith <mary@example.net>
    25  Subject: Saying Hello
    26  Date: Fri, 21 Nov 1997 09:55:06 -0600
    27  Message-ID: <1234@local.machine.example>
    28  
    29  This is a message just to say hello.
    30  So, "Hello".
    31  `,
    32  		header: Header{
    33  			"From":       []string{"John Doe <jdoe@machine.example>"},
    34  			"To":         []string{"Mary Smith <mary@example.net>"},
    35  			"Subject":    []string{"Saying Hello"},
    36  			"Date":       []string{"Fri, 21 Nov 1997 09:55:06 -0600"},
    37  			"Message-Id": []string{"<1234@local.machine.example>"},
    38  		},
    39  		body: "This is a message just to say hello.\nSo, \"Hello\".\n",
    40  	},
    41  }
    42  
    43  func TestParsing(t *testing.T) {
    44  	for i, test := range parseTests {
    45  		msg, err := ReadMessage(bytes.NewBuffer([]byte(test.in)))
    46  		if err != nil {
    47  			t.Errorf("test #%d: Failed parsing message: %v", i, err)
    48  			continue
    49  		}
    50  		if !headerEq(msg.Header, test.header) {
    51  			t.Errorf("test #%d: Incorrectly parsed message header.\nGot:\n%+v\nWant:\n%+v",
    52  				i, msg.Header, test.header)
    53  		}
    54  		body, err := ioutil.ReadAll(msg.Body)
    55  		if err != nil {
    56  			t.Errorf("test #%d: Failed reading body: %v", i, err)
    57  			continue
    58  		}
    59  		bodyStr := string(body)
    60  		if bodyStr != test.body {
    61  			t.Errorf("test #%d: Incorrectly parsed message body.\nGot:\n%+v\nWant:\n%+v",
    62  				i, bodyStr, test.body)
    63  		}
    64  	}
    65  }
    66  
    67  func headerEq(a, b Header) bool {
    68  	if len(a) != len(b) {
    69  		return false
    70  	}
    71  	for k, as := range a {
    72  		bs, ok := b[k]
    73  		if !ok {
    74  			return false
    75  		}
    76  		if !reflect.DeepEqual(as, bs) {
    77  			return false
    78  		}
    79  	}
    80  	return true
    81  }
    82  
    83  func TestDateParsing(t *testing.T) {
    84  	tests := []struct {
    85  		dateStr string
    86  		exp     time.Time
    87  	}{
    88  		// RFC 5322, Appendix A.1.1
    89  		{
    90  			"Fri, 21 Nov 1997 09:55:06 -0600",
    91  			time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", -6*60*60)),
    92  		},
    93  		// RFC5322, Appendix A.6.2
    94  		// Obsolete date.
    95  		{
    96  			"21 Nov 97 09:55:06 GMT",
    97  			time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("GMT", 0)),
    98  		},
    99  		// Commonly found format not specified by RFC 5322.
   100  		{
   101  			"Fri, 21 Nov 1997 09:55:06 -0600 (MDT)",
   102  			time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", -6*60*60)),
   103  		},
   104  	}
   105  	for _, test := range tests {
   106  		hdr := Header{
   107  			"Date": []string{test.dateStr},
   108  		}
   109  		date, err := hdr.Date()
   110  		if err != nil {
   111  			t.Errorf("Failed parsing %q: %v", test.dateStr, err)
   112  			continue
   113  		}
   114  		if !date.Equal(test.exp) {
   115  			t.Errorf("Parse of %q: got %+v, want %+v", test.dateStr, date, test.exp)
   116  		}
   117  	}
   118  }
   119  
   120  func TestAddressParsingError(t *testing.T) {
   121  	const txt = "=?iso-8859-2?Q?Bogl=E1rka_Tak=E1cs?= <unknown@gmail.com>"
   122  	_, err := ParseAddress(txt)
   123  	if err == nil || !strings.Contains(err.Error(), "charset not supported") {
   124  		t.Errorf(`mail.ParseAddress(%q) err: %q, want ".*charset not supported.*"`, txt, err)
   125  	}
   126  }
   127  
   128  func TestAddressParsing(t *testing.T) {
   129  	tests := []struct {
   130  		addrsStr string
   131  		exp      []*Address
   132  	}{
   133  		// Bare address
   134  		{
   135  			`jdoe@machine.example`,
   136  			[]*Address{{
   137  				Address: "jdoe@machine.example",
   138  			}},
   139  		},
   140  		// RFC 5322, Appendix A.1.1
   141  		{
   142  			`John Doe <jdoe@machine.example>`,
   143  			[]*Address{{
   144  				Name:    "John Doe",
   145  				Address: "jdoe@machine.example",
   146  			}},
   147  		},
   148  		// RFC 5322, Appendix A.1.2
   149  		{
   150  			`"Joe Q. Public" <john.q.public@example.com>`,
   151  			[]*Address{{
   152  				Name:    "Joe Q. Public",
   153  				Address: "john.q.public@example.com",
   154  			}},
   155  		},
   156  		{
   157  			`Mary Smith <mary@x.test>, jdoe@example.org, Who? <one@y.test>`,
   158  			[]*Address{
   159  				{
   160  					Name:    "Mary Smith",
   161  					Address: "mary@x.test",
   162  				},
   163  				{
   164  					Address: "jdoe@example.org",
   165  				},
   166  				{
   167  					Name:    "Who?",
   168  					Address: "one@y.test",
   169  				},
   170  			},
   171  		},
   172  		{
   173  			`<boss@nil.test>, "Giant; \"Big\" Box" <sysservices@example.net>`,
   174  			[]*Address{
   175  				{
   176  					Address: "boss@nil.test",
   177  				},
   178  				{
   179  					Name:    `Giant; "Big" Box`,
   180  					Address: "sysservices@example.net",
   181  				},
   182  			},
   183  		},
   184  		// RFC 5322, Appendix A.1.3
   185  		// TODO(dsymonds): Group addresses.
   186  
   187  		// RFC 2047 "Q"-encoded ISO-8859-1 address.
   188  		{
   189  			`=?iso-8859-1?q?J=F6rg_Doe?= <joerg@example.com>`,
   190  			[]*Address{
   191  				{
   192  					Name:    `Jörg Doe`,
   193  					Address: "joerg@example.com",
   194  				},
   195  			},
   196  		},
   197  		// RFC 2047 "Q"-encoded US-ASCII address. Dumb but legal.
   198  		{
   199  			`=?us-ascii?q?J=6Frg_Doe?= <joerg@example.com>`,
   200  			[]*Address{
   201  				{
   202  					Name:    `Jorg Doe`,
   203  					Address: "joerg@example.com",
   204  				},
   205  			},
   206  		},
   207  		// RFC 2047 "Q"-encoded UTF-8 address.
   208  		{
   209  			`=?utf-8?q?J=C3=B6rg_Doe?= <joerg@example.com>`,
   210  			[]*Address{
   211  				{
   212  					Name:    `Jörg Doe`,
   213  					Address: "joerg@example.com",
   214  				},
   215  			},
   216  		},
   217  		// RFC 2047, Section 8.
   218  		{
   219  			`=?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>`,
   220  			[]*Address{
   221  				{
   222  					Name:    `André Pirard`,
   223  					Address: "PIRARD@vm1.ulg.ac.be",
   224  				},
   225  			},
   226  		},
   227  		// Custom example of RFC 2047 "B"-encoded ISO-8859-1 address.
   228  		{
   229  			`=?ISO-8859-1?B?SvZyZw==?= <joerg@example.com>`,
   230  			[]*Address{
   231  				{
   232  					Name:    `Jörg`,
   233  					Address: "joerg@example.com",
   234  				},
   235  			},
   236  		},
   237  		// Custom example of RFC 2047 "B"-encoded UTF-8 address.
   238  		{
   239  			`=?UTF-8?B?SsO2cmc=?= <joerg@example.com>`,
   240  			[]*Address{
   241  				{
   242  					Name:    `Jörg`,
   243  					Address: "joerg@example.com",
   244  				},
   245  			},
   246  		},
   247  		// Custom example with "." in name. For issue 4938
   248  		{
   249  			`Asem H. <noreply@example.com>`,
   250  			[]*Address{
   251  				{
   252  					Name:    `Asem H.`,
   253  					Address: "noreply@example.com",
   254  				},
   255  			},
   256  		},
   257  	}
   258  	for _, test := range tests {
   259  		if len(test.exp) == 1 {
   260  			addr, err := ParseAddress(test.addrsStr)
   261  			if err != nil {
   262  				t.Errorf("Failed parsing (single) %q: %v", test.addrsStr, err)
   263  				continue
   264  			}
   265  			if !reflect.DeepEqual([]*Address{addr}, test.exp) {
   266  				t.Errorf("Parse (single) of %q: got %+v, want %+v", test.addrsStr, addr, test.exp)
   267  			}
   268  		}
   269  
   270  		addrs, err := ParseAddressList(test.addrsStr)
   271  		if err != nil {
   272  			t.Errorf("Failed parsing (list) %q: %v", test.addrsStr, err)
   273  			continue
   274  		}
   275  		if !reflect.DeepEqual(addrs, test.exp) {
   276  			t.Errorf("Parse (list) of %q: got %+v, want %+v", test.addrsStr, addrs, test.exp)
   277  		}
   278  	}
   279  }
   280  
   281  func TestAddressFormatting(t *testing.T) {
   282  	tests := []struct {
   283  		addr *Address
   284  		exp  string
   285  	}{
   286  		{
   287  			&Address{Address: "bob@example.com"},
   288  			"<bob@example.com>",
   289  		},
   290  		{
   291  			&Address{Name: "Bob", Address: "bob@example.com"},
   292  			`"Bob" <bob@example.com>`,
   293  		},
   294  		{
   295  			// note the ö (o with an umlaut)
   296  			&Address{Name: "Böb", Address: "bob@example.com"},
   297  			`=?utf-8?q?B=C3=B6b?= <bob@example.com>`,
   298  		},
   299  		{
   300  			&Address{Name: "Bob Jane", Address: "bob@example.com"},
   301  			`"Bob Jane" <bob@example.com>`,
   302  		},
   303  		{
   304  			&Address{Name: "Böb Jacöb", Address: "bob@example.com"},
   305  			`=?utf-8?q?B=C3=B6b_Jac=C3=B6b?= <bob@example.com>`,
   306  		},
   307  	}
   308  	for _, test := range tests {
   309  		s := test.addr.String()
   310  		if s != test.exp {
   311  			t.Errorf("Address%+v.String() = %v, want %v", *test.addr, s, test.exp)
   312  		}
   313  	}
   314  }