9 "github.com/mjl-/mox/dns"
10 "github.com/mjl-/mox/smtp"
11 "github.com/mjl-/mox/smtpclient"
12 "github.com/mjl-/mox/store"
15// Check user can submit message with message From address they are member of.
16func TestAliasSubmitMsgFrom(t *testing.T) {
17 ts := newTestServer(t, filepath.FromSlash("../testdata/smtp/mox.conf"), dns.MockResolver{})
21 ts.user = "mjl@mox.example"
24 var msg = strings.ReplaceAll(`From: <public@mox.example>
25To: <public@mox.example>
31 ts.run(func(client *smtpclient.Client) {
32 mailFrom := "mjl@mox.example"
33 rcptTo := "public@mox.example"
34 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
38 ts.run(func(client *smtpclient.Client) {
39 mailFrom := "public@mox.example" // List address as smtp mail from.
40 rcptTo := "public@mox.example"
41 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
45 msg = strings.ReplaceAll(`From: <private@mox.example>
46To: <private@mox.example>
52 ts.run(func(client *smtpclient.Client) {
53 mailFrom := "mjl@mox.example"
54 rcptTo := "private@mox.example"
55 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
56 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7DeliveryUnauth1})
59 ts.run(func(client *smtpclient.Client) {
60 mailFrom := "private@mox.example" // List address as smtp mail from.
61 rcptTo := "private@mox.example"
62 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
63 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7DeliveryUnauth1})
67// Non-member cannot submit as alias that allows it for members.
68func TestAliasSubmitMsgFromDenied(t *testing.T) {
69 ts := newTestServer(t, filepath.FromSlash("../testdata/smtp/mox.conf"), dns.MockResolver{})
72 // Trying to open account by alias should result in proper error.
73 _, _, _, err := store.OpenEmail(pkglog, "public@mox.example", false)
74 if err == nil || !errors.Is(err, store.ErrUnknownCredentials) {
75 t.Fatalf("opening alias, got err %v, expected store.ErrUnknownCredentials", err)
78 acc, err := store.OpenAccount(pkglog, "☺", false)
79 tcheck(t, err, "open account")
80 err = acc.SetPassword(pkglog, password0)
81 tcheck(t, err, "set password")
83 tcheck(t, err, "close account")
87 ts.user = "☺@mox.example"
90 var msg = strings.ReplaceAll(`From: <public@mox.example>
91To: <public@mox.example>
97 ts.run(func(client *smtpclient.Client) {
98 mailFrom := "☺@mox.example"
99 rcptTo := "public@mox.example"
100 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), true, true, false)
101 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7DeliveryUnauth1})
104 ts.run(func(client *smtpclient.Client) {
105 mailFrom := "public@mox.example" // List address as message from.
106 rcptTo := "public@mox.example"
107 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), true, true, false)
108 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7DeliveryUnauth1})
112// Non-member can deliver to public list, not to private list.
113func TestAliasDeliverNonMember(t *testing.T) {
114 resolver := dns.MockResolver{
115 A: map[string][]string{
116 "example.org.": {"127.0.0.10"}, // For mx check.
118 PTR: map[string][]string{
119 "127.0.0.10": {"example.org."}, // To get passed junk filter.
122 ts := newTestServer(t, filepath.FromSlash("../testdata/smtp/mox.conf"), resolver)
125 var msg = strings.ReplaceAll(`From: <other@example.org>
126To: <private@mox.example>
131 ts.run(func(client *smtpclient.Client) {
132 mailFrom := "other@example.org"
133 rcptTo := "private@mox.example"
134 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
135 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7ExpnProhibited2})
138 msg = strings.ReplaceAll(`From: <private@mox.example>
139To: <private@mox.example>
144 ts.run(func(client *smtpclient.Client) {
145 mailFrom := "private@example.org"
146 rcptTo := "private@mox.example"
147 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
148 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7ExpnProhibited2})
151 msg = strings.ReplaceAll(`From: <other@example.org>
152To: <public@mox.example>
158 ts.run(func(client *smtpclient.Client) {
159 mailFrom := "other@example.org"
160 rcptTo := "public@mox.example"
161 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
164 ts.checkCount("Inbox", 2) // Receiving for both mjl@ and móx@.
167 ts.run(func(client *smtpclient.Client) {
168 mailFrom := "public@example.org" // List address as message from.
169 rcptTo := "public@mox.example"
170 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
173 ts.checkCount("Inbox", 4) // Receiving for both mjl@ and móx@.
177// Member can deliver to private list, but still not with alias address as message
178// from. Message with alias from address as message from is allowed.
179func TestAliasDeliverMember(t *testing.T) {
180 resolver := dns.MockResolver{
181 A: map[string][]string{
182 "mox.example.": {"127.0.0.10"}, // For mx check.
184 PTR: map[string][]string{
185 "127.0.0.10": {"mox.example."}, // To get passed junk filter.
187 TXT: map[string][]string{
188 "mox.example.": {"v=spf1 ip4:127.0.0.10 -all"}, // To allow multiple recipients in transaction.
191 ts := newTestServer(t, filepath.FromSlash("../testdata/smtp/mox.conf"), resolver)
194 var msg = strings.ReplaceAll(`From: <mjl@mox.example>
195To: <private@mox.example>
200 ts.run(func(client *smtpclient.Client) {
201 mailFrom := "mjl@mox.example"
202 rcptTo := []string{"private@mox.example", "móx@mox.example"}
203 _, err := client.DeliverMultiple(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), true, true, false)
204 // assuming there wasn't a per-recipient error
207 ts.checkCount("Inbox", 1) // Receiving once. For explicit móx@ recipient, not for mjl@ due to msgfrom, and another again for móx@ due to rcpt to.
210 ts.run(func(client *smtpclient.Client) {
211 mailFrom := "mjl@mox.example"
212 rcptTo := "private@mox.example"
213 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
216 ts.checkCount("Inbox", 2) // Only receiving 1 new message compared to previous, for móx@mox.example, not mjl@.
219 msg = strings.ReplaceAll(`From: <private@mox.example>
220To: <private@mox.example>
226 ts.run(func(client *smtpclient.Client) {
227 mailFrom := "other@mox.example"
228 rcptTo := "private@mox.example"
229 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
230 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7ExpnProhibited2})
233 msg = strings.ReplaceAll(`From: <public@mox.example>
234To: <public@mox.example>
240 ts.run(func(client *smtpclient.Client) {
241 mailFrom := "mjl@mox.example"
242 rcptTo := "public@mox.example"
243 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
248// Message is rejected if no member accepts it.
249func TestAliasDeliverReject(t *testing.T) {
250 resolver := dns.MockResolver{
251 A: map[string][]string{
252 "mox.example.": {"127.0.0.10"}, // For mx check.
254 PTR: map[string][]string{
255 "127.0.0.10": {"mox.example."}, // To get passed junk filter.
257 TXT: map[string][]string{
258 "mox.example.": {"v=spf1 ip4:127.0.0.10 -all"}, // To allow multiple recipients in transaction.
261 ts := newTestServer(t, filepath.FromSlash("../testdata/smtp/mox.conf"), resolver)
264 var msg = strings.ReplaceAll(`From: <mjl@mox.example>
265To: <private@mox.example>
270 ts.run(func(client *smtpclient.Client) {
271 mailFrom := "mjl@mox.example"
272 rcptTo := "private@mox.example"
273 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
276 ts.checkCount("Inbox", 1) // Only receiving for móx@mox.example, not mjl@.
279 // Mark message as junk.
280 ts.xops.MessageFlagsAdd(ctxbg, pkglog, ts.acc, []int64{1}, []string{"$Junk"})
282 ts.run(func(client *smtpclient.Client) {
283 mailFrom := "mjl@mox.example"
284 rcptTo := "private@mox.example"
285 err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
286 ts.smtpErr(err, &smtpclient.Error{Code: smtp.C451LocalErr, Secode: smtp.SeSys3Other0})