go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/gae/impl/memory/mail_test.go (about)

     1  // Copyright 2015 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package memory
    16  
    17  import (
    18  	"context"
    19  	net_mail "net/mail"
    20  	"testing"
    21  
    22  	"go.chromium.org/luci/gae/service/mail"
    23  	"go.chromium.org/luci/gae/service/user"
    24  
    25  	. "github.com/smartystreets/goconvey/convey"
    26  	. "go.chromium.org/luci/common/testing/assertions"
    27  )
    28  
    29  func TestMail(t *testing.T) {
    30  	t.Parallel()
    31  
    32  	Convey("mail", t, func() {
    33  		c := Use(context.Background())
    34  
    35  		Convey("good cases", func() {
    36  			Convey("start with an empty set of messages", func() {
    37  				So(mail.GetTestable(c).SentMessages(), ShouldBeEmpty)
    38  			})
    39  
    40  			Convey("can send a message from the admin", func() {
    41  				So(mail.Send(c, &mail.Message{
    42  					Sender:  "admin@example.com",
    43  					To:      []string{"Valued Customer <customer@example.com>"},
    44  					Subject: "You are valued.",
    45  					Body:    "We value you.",
    46  				}), ShouldBeNil)
    47  
    48  				Convey("and it shows up in sent messages", func() {
    49  					So(mail.GetTestable(c).SentMessages(), ShouldResemble, []*mail.TestMessage{
    50  						{Message: mail.Message{
    51  							Sender:  "admin@example.com",
    52  							To:      []string{"Valued Customer <customer@example.com>"},
    53  							Subject: "You are valued.",
    54  							Body:    "We value you.",
    55  						}},
    56  					})
    57  
    58  					Convey("which can be reset", func() {
    59  						mail.GetTestable(c).Reset()
    60  						So(mail.GetTestable(c).SentMessages(), ShouldBeEmpty)
    61  					})
    62  				})
    63  			})
    64  
    65  			Convey("can send a message on behalf of a user", func() {
    66  				user.GetTestable(c).Login("dood@example.com", "", false)
    67  				So(mail.Send(c, &mail.Message{
    68  					Sender:  "Friendly Person <dood@example.com>",
    69  					To:      []string{"Other Friendly Person <dudette@example.com>"},
    70  					Subject: "Hi",
    71  					Body:    "An app is sending a message for me. It's the future.",
    72  				}), ShouldBeNil)
    73  			})
    74  
    75  			Convey("can send a message to the admins", func() {
    76  				So(mail.SendToAdmins(c, &mail.Message{
    77  					Sender:  "admin@example.com",
    78  					Subject: "Reminder",
    79  					Body:    "I forgot",
    80  				}), ShouldBeNil)
    81  
    82  				So(mail.GetTestable(c).SentMessages(), ShouldResemble, []*mail.TestMessage{
    83  					{Message: mail.Message{
    84  						Sender:  "admin@example.com",
    85  						To:      []string{"admin@example.com"},
    86  						Subject: "Reminder",
    87  						Body:    "I forgot",
    88  					}},
    89  				})
    90  			})
    91  
    92  			Convey("can set admin emails", func() {
    93  				mail.GetTestable(c).SetAdminEmails(
    94  					"Friendly <hello@example.com>",
    95  					"Epic <nerdsnipe@example.com>",
    96  				)
    97  
    98  				So(mail.SendToAdmins(c, &mail.Message{
    99  					Sender:  "hello@example.com",
   100  					Subject: "Reminder",
   101  					Body:    "I forgot",
   102  				}), ShouldBeNil)
   103  
   104  				So(mail.GetTestable(c).SentMessages(), ShouldResemble, []*mail.TestMessage{
   105  					{Message: mail.Message{
   106  						Sender: "hello@example.com",
   107  						To: []string{
   108  							"Friendly <hello@example.com>",
   109  							"Epic <nerdsnipe@example.com>",
   110  						},
   111  						Subject: "Reminder",
   112  						Body:    "I forgot",
   113  					}},
   114  				})
   115  			})
   116  
   117  			Convey("attachments get mimetypes assigned to them", func() {
   118  				So(mail.SendToAdmins(c, &mail.Message{
   119  					Sender:  "admin@example.com",
   120  					Subject: "Reminder",
   121  					Body:    "I forgot",
   122  					Attachments: []mail.Attachment{
   123  						{Name: "reminder.txt", Data: []byte("bananas")},
   124  						{Name: "coolthing", Data: []byte("bananas")},
   125  					},
   126  				}), ShouldBeNil)
   127  
   128  				So(mail.GetTestable(c).SentMessages(), ShouldResemble, []*mail.TestMessage{
   129  					{
   130  						Message: mail.Message{
   131  							Sender:  "admin@example.com",
   132  							To:      []string{"admin@example.com"},
   133  							Subject: "Reminder",
   134  							Body:    "I forgot",
   135  							Attachments: []mail.Attachment{
   136  								{Name: "reminder.txt", Data: []byte("bananas")},
   137  								{Name: "coolthing", Data: []byte("bananas")},
   138  							},
   139  						},
   140  						MIMETypes: []string{"text/plain", "application/octet-stream"}},
   141  				})
   142  			})
   143  
   144  			Convey("can have headers", func() {
   145  				So(mail.SendToAdmins(c, &mail.Message{
   146  					Sender:  "admin@example.com",
   147  					Subject: "Reminder",
   148  					Body:    "I forgot",
   149  					Headers: net_mail.Header{
   150  						"in-reply-to": []string{"epicness"},
   151  						"List-Id":     []string{"spam"},
   152  					},
   153  				}), ShouldBeNil)
   154  
   155  				So(mail.GetTestable(c).SentMessages(), ShouldResemble, []*mail.TestMessage{
   156  					{Message: mail.Message{
   157  						Sender:  "admin@example.com",
   158  						To:      []string{"admin@example.com"},
   159  						Subject: "Reminder",
   160  						Body:    "I forgot",
   161  						Headers: net_mail.Header{
   162  							"In-Reply-To": []string{"epicness"},
   163  							"List-Id":     []string{"spam"},
   164  						},
   165  					}},
   166  				})
   167  
   168  			})
   169  		})
   170  
   171  		Convey("errors", func() {
   172  			Convey("setting a non-email is a panic", func() {
   173  				So(func() { mail.GetTestable(c).SetAdminEmails("i am a banana") },
   174  					ShouldPanicLike, `invalid email ("i am a banana")`)
   175  			})
   176  
   177  			Convey("sending from a non-user, non-admin is an error", func() {
   178  				mail.GetTestable(c).SetAdminEmails("Friendly <hello@example.com>")
   179  
   180  				So(mail.Send(c, &mail.Message{
   181  					Sender:  "someone_else@example.com",
   182  					Subject: "Reminder",
   183  					Body:    "I forgot",
   184  				}), ShouldErrLike, "invalid Sender: someone_else@example.com")
   185  			})
   186  
   187  			Convey("sending from a bogus address is a problem", func() {
   188  				So(mail.Send(c, &mail.Message{
   189  					Sender: "lalal",
   190  				}), ShouldErrLike, "unparsable Sender address: lalal")
   191  			})
   192  
   193  			Convey("sending with no recipients is a problem", func() {
   194  				So(mail.Send(c, &mail.Message{
   195  					Sender: "admin@example.com",
   196  				}), ShouldErrLike, "one of To, Cc or Bcc must be non-empty")
   197  			})
   198  
   199  			Convey("bad addresses are a problem", func() {
   200  				So(mail.Send(c, &mail.Message{
   201  					Sender: "admin@example.com",
   202  					To:     []string{"wut"},
   203  				}), ShouldErrLike, `invalid email ("wut")`)
   204  
   205  				So(mail.Send(c, &mail.Message{
   206  					Sender: "admin@example.com",
   207  					Cc:     []string{"wut"},
   208  				}), ShouldErrLike, `invalid email ("wut")`)
   209  
   210  				So(mail.Send(c, &mail.Message{
   211  					Sender: "admin@example.com",
   212  					Bcc:    []string{"wut"},
   213  				}), ShouldErrLike, `invalid email ("wut")`)
   214  			})
   215  
   216  			Convey("no body is a problem", func() {
   217  				So(mail.Send(c, &mail.Message{
   218  					Sender: "admin@example.com",
   219  					To:     []string{"wut@example.com"},
   220  				}), ShouldErrLike, `one of Body or HTMLBody must be non-empty`)
   221  			})
   222  
   223  			Convey("bad attachments are a problem", func() {
   224  				So(mail.Send(c, &mail.Message{
   225  					Sender: "admin@example.com",
   226  					To:     []string{"wut@example.com"},
   227  					Body:   "nice thing",
   228  					Attachments: []mail.Attachment{
   229  						{Name: "nice.exe", Data: []byte("boom")},
   230  					},
   231  				}), ShouldErrLike, `illegal attachment extension for "nice.exe"`)
   232  			})
   233  
   234  			Convey("bad headers are a problem", func() {
   235  				So(mail.SendToAdmins(c, &mail.Message{
   236  					Sender:  "admin@example.com",
   237  					Subject: "Reminder",
   238  					Body:    "I forgot",
   239  					Headers: net_mail.Header{"x-spam-cool": []string{"value"}},
   240  				}), ShouldErrLike, `disallowed header: x-spam-cool`)
   241  
   242  			})
   243  
   244  		})
   245  
   246  	})
   247  }