8 "github.com/mjl-/bstore"
10 "github.com/mjl-/mox/dns"
11 "github.com/mjl-/mox/smtp"
12 "github.com/mjl-/mox/smtpclient"
13 "github.com/mjl-/mox/store"
16// Check user can submit message with message From address they are member of.
17func TestAliasSubmitMsgFrom(t *testing.T) {
18 ts := newTestServer(t, filepath.FromSlash("../testdata/smtp/mox.conf"), dns.MockResolver{})
22 ts.user = "mjl@mox.example"
25 var msg = strings.ReplaceAll(`From: <public@mox.example>
26To: <public@mox.example>
32 ts.run(func(err error, client *smtpclient.Client) {
34 mailFrom := "mjl@mox.example"
35 rcptTo := "public@mox.example"
37 err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
42 msg = strings.ReplaceAll(`From: <private@mox.example>
43To: <private@mox.example>
49 ts.run(func(err error, client *smtpclient.Client) {
51 mailFrom := "mjl@mox.example"
52 rcptTo := "private@mox.example"
54 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})
60// Non-member cannot submit as alias that allows it for members.
61func TestAliasSubmitMsgFromDenied(t *testing.T) {
62 ts := newTestServer(t, filepath.FromSlash("../testdata/smtp/mox.conf"), dns.MockResolver{})
65 acc, err := store.OpenAccount(pkglog, "☺")
66 tcheck(t, err, "open account")
67 err = acc.SetPassword(pkglog, password0)
68 tcheck(t, err, "set password")
70 tcheck(t, err, "close account")
74 ts.user = "☺@mox.example"
77 var msg = strings.ReplaceAll(`From: <public@mox.example>
78To: <public@mox.example>
84 ts.run(func(err error, client *smtpclient.Client) {
86 mailFrom := "☺@mox.example"
87 rcptTo := "public@mox.example"
89 err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), true, true, false)
91 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7DeliveryUnauth1})
95// Non-member can deliver to public list, not to private list.
96func TestAliasDeliverNonMember(t *testing.T) {
97 resolver := dns.MockResolver{
98 A: map[string][]string{
99 "example.org.": {"127.0.0.10"}, // For mx check.
101 PTR: map[string][]string{
102 "127.0.0.10": {"example.org."}, // To get passed junk filter.
105 ts := newTestServer(t, filepath.FromSlash("../testdata/smtp/mox.conf"), resolver)
108 var msg = strings.ReplaceAll(`From: <other@example.org>
109To: <private@mox.example>
114 ts.run(func(err error, client *smtpclient.Client) {
116 mailFrom := "other@example.org"
117 rcptTo := "private@mox.example"
119 err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
121 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7ExpnProhibited2})
124 msg = strings.ReplaceAll(`From: <private@mox.example>
125To: <private@mox.example>
130 ts.run(func(err error, client *smtpclient.Client) {
132 mailFrom := "private@example.org"
133 rcptTo := "private@mox.example"
135 err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
137 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7ExpnProhibited2})
140 msg = strings.ReplaceAll(`From: <other@example.org>
141To: <public@mox.example>
147 ts.run(func(err error, client *smtpclient.Client) {
149 mailFrom := "other@example.org"
150 rcptTo := "public@mox.example"
152 err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
156 ts.checkCount("Inbox", 2) // Receiving for both mjl@ and móx@.
160// Member can deliver to private list, but still not with alias address as message
161// from. Message with alias from address as message from is allowed.
162func TestAliasDeliverMember(t *testing.T) {
163 resolver := dns.MockResolver{
164 A: map[string][]string{
165 "mox.example.": {"127.0.0.10"}, // For mx check.
167 PTR: map[string][]string{
168 "127.0.0.10": {"mox.example."}, // To get passed junk filter.
170 TXT: map[string][]string{
171 "mox.example.": {"v=spf1 ip4:127.0.0.10 -all"}, // To allow multiple recipients in transaction.
174 ts := newTestServer(t, filepath.FromSlash("../testdata/smtp/mox.conf"), resolver)
177 var msg = strings.ReplaceAll(`From: <mjl@mox.example>
178To: <private@mox.example>
183 ts.run(func(err error, client *smtpclient.Client) {
185 mailFrom := "mjl@mox.example"
186 rcptTo := []string{"private@mox.example", "móx@mox.example"}
188 _, err = client.DeliverMultiple(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), true, true, false)
189 // assuming there wasn't a per-recipient error
193 ts.checkCount("Inbox", 0) // Not receiving for mjl@ due to msgfrom, and not móx@ due to rcpt to.
196 ts.run(func(err error, client *smtpclient.Client) {
198 mailFrom := "mjl@mox.example"
199 rcptTo := "private@mox.example"
201 err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
205 ts.checkCount("Inbox", 1) // Only receiving for móx@mox.example, not mjl@.
208 msg = strings.ReplaceAll(`From: <private@mox.example>
209To: <private@mox.example>
215 ts.run(func(err error, client *smtpclient.Client) {
217 mailFrom := "other@mox.example"
218 rcptTo := "private@mox.example"
220 err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
222 ts.smtpErr(err, &smtpclient.Error{Permanent: true, Code: smtp.C550MailboxUnavail, Secode: smtp.SePol7ExpnProhibited2})
225 msg = strings.ReplaceAll(`From: <public@mox.example>
226To: <public@mox.example>
232 ts.run(func(err error, client *smtpclient.Client) {
234 mailFrom := "mjl@mox.example"
235 rcptTo := "public@mox.example"
237 err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
243// Message is rejected if no member accepts it.
244func TestAliasDeliverReject(t *testing.T) {
245 resolver := dns.MockResolver{
246 A: map[string][]string{
247 "mox.example.": {"127.0.0.10"}, // For mx check.
249 PTR: map[string][]string{
250 "127.0.0.10": {"mox.example."}, // To get passed junk filter.
252 TXT: map[string][]string{
253 "mox.example.": {"v=spf1 ip4:127.0.0.10 -all"}, // To allow multiple recipients in transaction.
256 ts := newTestServer(t, filepath.FromSlash("../testdata/smtp/mox.conf"), resolver)
259 var msg = strings.ReplaceAll(`From: <mjl@mox.example>
260To: <private@mox.example>
265 ts.run(func(err error, client *smtpclient.Client) {
267 mailFrom := "mjl@mox.example"
268 rcptTo := "private@mox.example"
270 err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
274 ts.checkCount("Inbox", 1) // Only receiving for móx@mox.example, not mjl@.
277 // Mark message as junk.
278 q := bstore.QueryDB[store.Message](ctxbg, ts.acc.DB)
279 n, err := q.UpdateFields(map[string]any{"Junk": true})
280 tcheck(t, err, "mark as junk")
283 ts.run(func(err error, client *smtpclient.Client) {
285 mailFrom := "mjl@mox.example"
286 rcptTo := "private@mox.example"
288 err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false, false)
290 ts.smtpErr(err, &smtpclient.Error{Code: smtp.C451LocalErr, Secode: smtp.SeSys3Other0})