1package main
2
3import (
4 "fmt"
5 "log"
6 "strings"
7
8 "github.com/mjl-/sconf"
9
10 "github.com/mjl-/mox/config"
11)
12
13func cmdExample(c *cmd) {
14 c.params = "[name]"
15 c.help = `List available examples, or print a specific example.`
16
17 args := c.Parse()
18 if len(args) > 1 {
19 c.Usage()
20 }
21
22 var match func() string
23 for _, ex := range examples {
24 if len(args) == 0 {
25 fmt.Println(ex.Name)
26 } else if args[0] == ex.Name {
27 match = ex.Get
28 }
29 }
30 if len(args) == 0 {
31 return
32 }
33 if match == nil {
34 log.Fatalln("not found")
35 }
36 fmt.Print(match())
37}
38
39var examples = []struct {
40 Name string
41 Get func() string
42}{
43 {
44 "webhandlers",
45 func() string {
46 const webhandlers = `# Snippet of domains.conf to configure WebDomainRedirects and WebHandlers.
47
48# Redirect all requests for mox.example to https://www.mox.example.
49WebDomainRedirects:
50 mox.example: www.mox.example
51
52# Each request is matched against these handlers until one matches and serves it.
53WebHandlers:
54 -
55 # Redirect all plain http requests to https, leaving path, query strings, etc
56 # intact. When the request is already to https, the destination URL would have the
57 # same scheme, host and path, causing this redirect handler to not match the
58 # request (and not cause a redirect loop) and the webserver to serve the request
59 # with a later handler.
60 LogName: redirhttps
61 Domain: www.mox.example
62 PathRegexp: ^/
63 # Could leave DontRedirectPlainHTTP at false if it wasn't for this being an
64 # example for doing this redirect.
65 DontRedirectPlainHTTP: true
66 WebRedirect:
67 BaseURL: https://www.mox.example
68 -
69 # The name of the handler, used in logging and metrics.
70 LogName: staticmjl
71 # With ACME configured, each configured domain will automatically get a TLS
72 # certificate on first request.
73 Domain: www.mox.example
74 PathRegexp: ^/who/mjl/
75 WebStatic:
76 StripPrefix: /who/mjl
77 # Requested path /who/mjl/inferno/ resolves to local web/mjl/inferno.
78 # If a directory contains an index.html, it is served when a directory is requested.
79 Root: web/mjl
80 # With ListFiles true, if a directory does not contain an index.html, the contents are listed.
81 ListFiles: true
82 ResponseHeaders:
83 X-Mox: hi
84 -
85 LogName: redir
86 Domain: www.mox.example
87 PathRegexp: ^/redir/a/b/c
88 # Don't redirect from plain HTTP to HTTPS.
89 DontRedirectPlainHTTP: true
90 WebRedirect:
91 # Just change the domain and add query string set fragment. No change to scheme.
92 # Path will start with /redir/a/b/c (and whathever came after) because no
93 # OrigPathRegexp+ReplacePath is set.
94 BaseURL: //moxest.example?q=1#frag
95 # Default redirection is 308 - Permanent Redirect.
96 StatusCode: 307
97 -
98 LogName: oldnew
99 Domain: www.mox.example
100 PathRegexp: ^/old/
101 WebRedirect:
102 # Replace path, leaving rest of URL intact.
103 OrigPathRegexp: ^/old/(.*)
104 ReplacePath: /new/$1
105 -
106 LogName: app
107 Domain: www.mox.example
108 PathRegexp: ^/app/
109 WebForward:
110 # Strip the path matched by PathRegexp before forwarding the request. So original
111 # request /app/api become just /api.
112 StripPath: true
113 # URL of backend, where requests are forwarded to. The path in the URL is kept,
114 # so for incoming request URL /app/api, the outgoing request URL has path /app-v2/api.
115 # Requests are made with Go's net/http DefaultTransporter, including using
116 # HTTP_PROXY and HTTPS_PROXY environment variables.
117 URL: http://127.0.0.1:8900/app-v2/
118 # Add headers to response.
119 ResponseHeaders:
120 X-Frame-Options: deny
121 X-Content-Type-Options: nosniff
122`
123 // Parse just so we know we have the syntax right.
124 // todo: ideally we would have a complete config file and parse it fully.
125 var conf struct {
126 WebDomainRedirects map[string]string
127 WebHandlers []config.WebHandler
128 }
129 err := sconf.Parse(strings.NewReader(webhandlers), &conf)
130 xcheckf(err, "parsing webhandlers example")
131 return webhandlers
132 },
133 },
134 {
135 "transport",
136 func() string {
137 const moxconf = `# Snippet for mox.conf, defining a transport called Example that connects on the
138# SMTP submission with TLS port 465 ("submissions), authenticating with
139# SCRAM-SHA-256-PLUS (other providers may not support SCRAM-SHA-256-PLUS, but they
140# typically do support the older CRAM-MD5).:
141
142# Transport are mechanisms for delivering messages. Transports can be referenced
143# from Routes in accounts, domains and the global configuration. There is always
144# an implicit/fallback delivery transport doing direct delivery with SMTP from the
145# outgoing message queue. Transports are typically only configured when using
146# smarthosts, i.e. when delivering through another SMTP server. Zero or one
147# transport methods must be set in a transport, never multiple. When using an
148# external party to send email for a domain, keep in mind you may have to add
149# their IP address to your domain's SPF record, and possibly additional DKIM
150# records. (optional)
151Transports:
152 Example:
153 # Submission SMTP over a TLS connection to submit email to a remote queue.
154 # (optional)
155 Submissions:
156 # Host name to connect to and for verifying its TLS certificate.
157 Host: smtp.example.com
158
159 # If set, authentication credentials for the remote server. (optional)
160 Auth:
161 Username: user@example.com
162 Password: test1234
163 Mechanisms:
164 # Allowed authentication mechanisms. Defaults to SCRAM-SHA-256-PLUS,
165 # SCRAM-SHA-256, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, CRAM-MD5. Not included by default:
166 # PLAIN. Specify the strongest mechanism known to be implemented by the server to
167 # prevent mechanism downgrade attacks. (optional)
168
169 - SCRAM-SHA-256-PLUS
170`
171
172 const domainsconf = `# Snippet for domains.conf, specifying a route that sends through the transport:
173
174# Routes for delivering outgoing messages through the queue. Each delivery attempt
175# evaluates account routes, domain routes and finally these global routes. The
176# transport of the first matching route is used in the delivery attempt. If no
177# routes match, which is the default with no configured routes, messages are
178# delivered directly from the queue. (optional)
179Routes:
180 -
181 Transport: Example
182`
183
184 var static struct {
185 Transports map[string]config.Transport
186 }
187 var dynamic struct {
188 Routes []config.Route
189 }
190 err := sconf.Parse(strings.NewReader(moxconf), &static)
191 xcheckf(err, "parsing moxconf example")
192 err = sconf.Parse(strings.NewReader(domainsconf), &dynamic)
193 xcheckf(err, "parsing domainsconf example")
194 return moxconf + "\n\n" + domainsconf
195 },
196 },
197}
198