| 1 | The =distorted.org.uk= mail system |
| 2 | |
| 3 | * Delivery |
| 4 | |
| 5 | The mail delivery agent is Exim. If you don't do anything special, mail |
| 6 | is delivered into =/var/mail/USER= on stratocaster, in mbox format. |
| 7 | |
| 8 | There are a number of ways you can affect mail delivery. |
| 9 | |
| 10 | ** The =~/.forward= file |
| 11 | |
| 12 | In traditional Unix style, you can write delivery instructions into a |
| 13 | file named =.forward= in your home directory. This file can contain a |
| 14 | comma-separated list of email address and/or file or directory names to |
| 15 | which your mail should be sent. Mail is written to files in traditional |
| 16 | Unix `mbox' format, and to directories in `Maildir' format. The |
| 17 | =:fail:= and =:defer:= items are permitted, but may not be very useful. |
| 18 | |
| 19 | This file can instead be an Exim or Sieve filter file, as marked by a |
| 20 | special comment on the first line. See the document `Exim's interfaces |
| 21 | to mail filtering', available via the command =info filter=, for details |
| 22 | about these files. |
| 23 | |
| 24 | ** The =~/.mail/forward= file |
| 25 | |
| 26 | If you prefer, you can write delivery instructions to =~/.mail/forward= |
| 27 | instead. If you have lots of mail configuration files, you may find it |
| 28 | tidier to keep them all together in =~/.mail/=. |
| 29 | |
| 30 | ** The =~/.mail/forward.suffix= file |
| 31 | |
| 32 | You will receive mail sent to =USER@distorted.org.uk=. You can also |
| 33 | receive mail sent to =USER-SUFFIX@distorted.org.uk= or |
| 34 | =USER+SUFFIX@distorted.org.uk=, for any =SUFFIX= string if you create a |
| 35 | file =~/.mail/forward.suffix=. While this can be a simple forward file, |
| 36 | it's probably much more useful to write an Exim filter file to analyse |
| 37 | the suffix string and take appropriate action. |
| 38 | |
| 39 | If this file exists, it should be world-readable, because it will be |
| 40 | used by the mail server at SMTP time in order to decide whether a |
| 41 | particular =SUFFIX= string is valid. |
| 42 | |
| 43 | ** Permissions for filter files |
| 44 | |
| 45 | Your various filter files are used by Exim's SMTP server, which runs as |
| 46 | an unprivileged user =Debian-exim= for security reasons. Therefore your |
| 47 | filter files must be readable by this user. Currently, the only way to |
| 48 | do this is to make the filter files world-readable. If this is |
| 49 | unsatisfactory for some reason I'll try to come up with a way to arrange |
| 50 | privacy for your filters. |
| 51 | |
| 52 | |
| 53 | * Reading mail |
| 54 | |
| 55 | ** Reading mail locally |
| 56 | |
| 57 | The servers =stratocaster= and =jem= have a few mail user agents |
| 58 | installed, most notably trad BSD =mail=, =mutt=, and Emacs's various |
| 59 | mail-reading interfaces; more can be added. Your mail is delivered to |
| 60 | =/var/mail/USER=; any further arrangements, e.g., multiple folders, are |
| 61 | left to you. |
| 62 | |
| 63 | ** Fetching mail through IMAP |
| 64 | |
| 65 | There's an IMAP server running on =mail.distorted.org.uk=. It expects |
| 66 | your main inbox to be in =/var/mail/USER=, and further folders are put |
| 67 | in =~/mail/=, in mbox format. |
| 68 | |
| 69 | The IMAP server listens on ports 143 (plain IMAP) and 993 (IMAP over |
| 70 | TLS). In the former case, you'll have to configure your client to send |
| 71 | =STARTTLS=, because the server simply won't allow non-encrypted |
| 72 | communication. |
| 73 | |
| 74 | The server's certificate is signed by my certificate authority, whose |
| 75 | own certificate can be fetched from |
| 76 | https://www.distorted.org.uk/ca/ca.cert. (The web server's certificate |
| 77 | is signed by the StartCom Class 1 CA, which should be in most browser's |
| 78 | certificate stores.) I issue new short-term certificates daily, so |
| 79 | telling your mail client to pin the certificate won't help. (The public |
| 80 | key doesn't change, though, so if you can do public-key pinning you'll |
| 81 | be OK.) |
| 82 | |
| 83 | ** Forwarding mail off-site |
| 84 | |
| 85 | You can redirect all of your mail to some other site if you prefer to |
| 86 | consolidate it: just write the destination mailbox to =~/.forward=. |
| 87 | Everything else is left to you. |
| 88 | |
| 89 | |
| 90 | * Sending mail |
| 91 | |
| 92 | ** The =sendmail= program |
| 93 | |
| 94 | Exim provides a =/usr/sbin/sendmail= program with a plausible interface, |
| 95 | and most traditional Unix programs will use this by default to send |
| 96 | mail. |
| 97 | |
| 98 | ** SMTP to =localhost= |
| 99 | |
| 100 | Another traditional way of submitting mail is by connecting to port 25 |
| 101 | on the loopback address 127.0.0.1 and speaking SMTP. This will work on |
| 102 | most servers, and you will be authenticated automatically using the |
| 103 | system's =identd=. NB: servers other than stratocaster won't |
| 104 | understand unusual domains. |
| 105 | |
| 106 | ** The Submission protocol |
| 107 | |
| 108 | The `modern' way to submit mail involves connecting to port 587 on the |
| 109 | =mail.distorted.org.uk= (the `submission' service) and speaking SMTP. |
| 110 | If you use this service, then (a) you must tell your client to send |
| 111 | =STARTTLS=, and (b) you will have to provide a user name and password. |
| 112 | |
| 113 | As with IMAP, the SMTP server's certificate is signed by the |
| 114 | =distorted.org.uk= CA; see above. |
| 115 | |
| 116 | ** Sender authenticity |
| 117 | |
| 118 | It is my intention that it be very hard for one =distorted.org.uk= user |
| 119 | to impersonate another to a third. To this end, the mail server is |
| 120 | rather picky about envelope sender addresses. |
| 121 | |
| 122 | + It won't accept an apparently local sender address from an external |
| 123 | mail server at all. |
| 124 | |
| 125 | + It will check locally submitted mail against the submitter's user |
| 126 | name. The precise details vary according to the submission |
| 127 | mechanism: mail submitted through =sendmail= will have additional |
| 128 | headers added; mail submitted through SMTP will be rejected unless |
| 129 | the envelope sender is acceptable. |
| 130 | |
| 131 | If I see something like DKIM catching on then this will also provide |
| 132 | external users with some kind of (probably fairly weak) sender |
| 133 | authenticity. |
| 134 | |
| 135 | On the other hand, the mail server is aware of vanity domains, extension |
| 136 | addresses, and so on, and should let you send mail apparently from an |
| 137 | such an address that you control. If you think the mail server is being |
| 138 | unnecessarily strict about something then I'm willing to discuss your |
| 139 | requirements. |
| 140 | |
| 141 | If I'm hosting your mail domain for you then you get to decide the |
| 142 | appropriate policy. |
| 143 | |
| 144 | |
| 145 | * Chopwood, and passwords |
| 146 | |
| 147 | Users don't have login passwords on =distorted.org.uk= machines; but the |
| 148 | SMTP and IMAP services require user names and passwords, which are |
| 149 | managed using the `Chopwood' service (whose name is `chpwd' -- short for |
| 150 | `change password' -- with some additional vowels). |
| 151 | |
| 152 | You can communicate with Chopwood in three different ways. |
| 153 | |
| 154 | 1. Using Userv. On stratocaster, run =userv chpwd help= for a list |
| 155 | of commands. |
| 156 | |
| 157 | 2. Using SSH. You will need to send me an SSH public key (or |
| 158 | several), which I'll install for you. Then you'll be able to run |
| 159 | =ssh chpwd@stratocaster.distorted.org.uk help= for a list of |
| 160 | commands, as for Userv. (This is mainly intended for people who |
| 161 | don't have login accounts.) |
| 162 | |
| 163 | 3. Using the web interface. Point your browser at |
| 164 | =https://www.distorted.org.uk/chpwd/=. For this, you'll need a |
| 165 | user name and password for Chopwood itself: if you have a local |
| 166 | login, you can set this up yourself using Userv (say); otherwise |
| 167 | I'll generate a password for you and send it to you. |
| 168 | |
| 169 | If you're using Userv or SSH, you can list which password-using services |
| 170 | you have accounts with the =list= command, and request new passwords |
| 171 | with =reset=, which prints the new password to stdout; the =clear= |
| 172 | command will disable a service's password, preventing you from logging |
| 173 | in at all. There is a command =set= for setting a password that you |
| 174 | choose, but that's disabled as a matter of local policy: it's possible |
| 175 | that I can be persuaded to enable it, but not very likely. Note that |
| 176 | you can reset several services' passwords with the same command, and |
| 177 | this will use the same (freshly generated) password for all of them. |
| 178 | For example, |
| 179 | |
| 180 | : userv chpwd reset smtp imap |
| 181 | |
| 182 | will generate a new password which will work both with the SMTP |
| 183 | submission service and the IMAP server. |
| 184 | |
| 185 | Similar functionality is available through the web interface. |
| 186 | |
| 187 | |
| 188 | * Spam filtering |
| 189 | |
| 190 | The mail server checks incoming mail using SpamAssassin at SMTP time. |
| 191 | Suspected spam is rejected immediately. There are no `junk' mail |
| 192 | folders. Legitimate senders will likely receive bounces; spammers will |
| 193 | probably ignore the error and continue. |
| 194 | |
| 195 | ** SpamAssassin |
| 196 | |
| 197 | SpamAssassin works by having a large collection of rules: it tests an |
| 198 | incoming message against these rules, and adds up the /scores/ for the |
| 199 | rules that match. If the total score is above a given threshold then |
| 200 | the message is declared to be probably spam, and rejected. |
| 201 | |
| 202 | If the mail server accepts a message, it adds two headers to it. |
| 203 | |
| 204 | + =X-SpamAssassin-Score= has the form =SCORE/LIMIT (BAR)=, where |
| 205 | =SCORE= is the actual score for the message, =LIMIT= is the maximum |
| 206 | score allowed, and =BAR= is a little bar chart showing the score in |
| 207 | a way which can be matched easily using regular expressions. The |
| 208 | bar chart uses =+= or =-= signs, depending on whether the score is |
| 209 | positive or negative, or consists of a single =/= sign if it's close |
| 210 | to zero. |
| 211 | |
| 212 | + =X-SpamAssassin-Status= consists of space-separated =KEY=VAUE= |
| 213 | pairs. The keys currently are: =score= and =limit=, which are the |
| 214 | message's score and limit again; and =tests=, which lists the rules |
| 215 | which matched the message and their individual scores, as a |
| 216 | comma-separated list of items of the form =RULE:SCORE=. |
| 217 | |
| 218 | ** Custom spam limits |
| 219 | |
| 220 | The default spam limit is currently 5 points. However, you can override |
| 221 | this limit for mail sent to you by creating a world-readable file |
| 222 | =~/.mail/spam-limit= in your home directory on stratocaster. This file |
| 223 | should contain lines of the form |
| 224 | |
| 225 | : PATTERN: LIMIT |
| 226 | |
| 227 | where =PATTERN= is an Exim =nwildlsearch= pattern matched against a |
| 228 | string of the form =RECIPIENT/SENDER=, and the =LIMIT= is ten times the |
| 229 | maximum SpamAssassin score you're willing to tolerate for this message. |
| 230 | See the Exim manual for full details; in short, the pattern may be a |
| 231 | literal string, a string beginning with a =*= to match a particular |
| 232 | suffix (usually a sender address or domain, which is why the sender is |
| 233 | on the right), or a Perl-style regular expression starting with =^=. |
| 234 | |
| 235 | You may not want information about who is sending you spam (or honest |
| 236 | but spamlike mail) to be public knowledge, so instead you can make a |
| 237 | file =~/.mail/spam-limit.userv= of the same format. This file need not |
| 238 | be readable by anyone other than you. |
| 239 | |
| 240 | Be careful with this facility: if a single incoming message has multiple |
| 241 | recipients, and they assign it different spam score limits (either |
| 242 | explicitly, or implicitly by accepting the system default) then the |
| 243 | sender will be told to defer delivery to some recipients. It's |
| 244 | therefore probably a bad idea to apply custom spam score limits for mail |
| 245 | for popular mailing lists, for example. |
| 246 | |
| 247 | ** SAUCE |
| 248 | |
| 249 | I'm not currently running SAUCE, but I'm giving it some consideration. |
| 250 | If you have comments on the matter, either way, I'm interested. |
| 251 | |
| 252 | |
| 253 | * Mail hosting and custom domains |
| 254 | |
| 255 | I think I have a fairly sane way to set up stratocaster (or some other |
| 256 | server, but strat is the obvious choice) to receive mail for domains |
| 257 | other than =distorted.org.uk=. I can easily arrange to accept mail for |
| 258 | such domains and deliver them locally or to other hosts. Pester me if |
| 259 | this sounds useful to you. |
| 260 | |
| 261 | |
| 262 | * Technical documentation |
| 263 | |
| 264 | ** =auth-sender.conf= |
| 265 | |
| 266 | This file is an =lsearch=-format map from user names to address lists |
| 267 | that the users are allowed to claim as envelope senders. (For domains |
| 268 | hosted locally, the *users* and *locals* options of =domains.conf= works |
| 269 | better: this mechanism is intended to allow users to send mail |
| 270 | apparently from their Gmail addresses, for example.) |
| 271 | |
| 272 | ** =domains.conf= |
| 273 | |
| 274 | Most of the special knowledge for the mail configuration is in |
| 275 | =/etc/mail/domains.conf=. This contains a number of stanzas, each |
| 276 | headed by a domain pattern, and containing a sequence of /key/ = /value/ |
| 277 | pairs. If a /value/ contains whitespace then it must be quoted. In |
| 278 | terms of Exim syntax, this is a `partial0-wildlsearch' file where the |
| 279 | values are =${extract ...}= strings. |
| 280 | |
| 281 | The following keys are recognized. Nothing will save you if you spell |
| 282 | the name of a key wrongly. |
| 283 | |
| 284 | + errors_to :: Sets =errors_to= for deliveries to a virtual domain -- |
| 285 | see [[info:spec:Generic%20options%20for%20routers][Generic options for routers]]. The default is to send errors to |
| 286 | the sender, as usual. |
| 287 | |
| 288 | + filter :: Specifies the name (subject to expansion) of a filter file |
| 289 | to use for routing mail to a virtual domain. The filter file may |
| 290 | use full the Exim filtering language, and may cause deferrals, |
| 291 | failures, or blackholing. This is one of a number of mutually |
| 292 | exclusive router options: see also *redirect* and *route*. |
| 293 | |
| 294 | + final :: If true (the default, if there is an entry for the |
| 295 | receiving domain), then recipients not routed through the |
| 296 | =domains.conf= file are assumed not to exist. (As a last ditch |
| 297 | measure, mail to the special local-parts =postmaster= and =abuse= is |
| 298 | redirected to the global administrator.) If false, local parts not |
| 299 | routed using the =domains.conf= machinery are handled as for the |
| 300 | main system domain. You probably don't want to turn this off; see |
| 301 | =sysusers= instead. |
| 302 | |
| 303 | + home :: The home directory for the virtual domain administrator. |
| 304 | This is available to other expansions as =$home=. |
| 305 | |
| 306 | + hosts :: A list of host names and/or addresses which are permitted |
| 307 | to send mail from this domain. If this key is omitted, but there is |
| 308 | a matching =domains.conf= entry for the domain, then the default is |
| 309 | the list of known networks =+allnets=; otherwise the default is all |
| 310 | external networks. |
| 311 | |
| 312 | + locals :: A list (expanded) of those local-parts which the |
| 313 | authenticated user (named by =$acl_c_user=) is permitted to use as |
| 314 | the sender on outgoing messages. |
| 315 | |
| 316 | + owner :: The name of the user who should perform local deliveries to |
| 317 | this virtual domain. |
| 318 | |
| 319 | + redirect :: Redirection data (expanded) for deliveries to this |
| 320 | virtual domain. This is one of a number of mutually exclusive |
| 321 | router options: see also *filter* and *route*. |
| 322 | |
| 323 | + require-auth :: If true, then the recipient domain requires us to |
| 324 | perform SMTP authentication to it. The necessary credentials are in |
| 325 | =/etc/mail/client-secrets=, which is in =partial0-lsearch= format, |
| 326 | keyed by either the recipient domain or host, and the values are |
| 327 | =${extract ...}=-format key/value pairs which depend on the |
| 328 | authenticator to use. For PLAIN authentication, set *plain* to the |
| 329 | string to send (using =^= to stand for NUL bytes, e.g., |
| 330 | =^user^passwd=). For LOGIN, set *login-name* and *login-passwd*. |
| 331 | For CRAM-MD5, set *cram-md5-name* and *cram-md5-secret*. |
| 332 | |
| 333 | + route :: Routing data (=route_data= for Exim's =manualroute= |
| 334 | transport) for sending mail to the domain. This is one of a number |
| 335 | of mutually exclusive router options: see also *filter* and |
| 336 | *redirect*. |
| 337 | |
| 338 | + senders :: A list of sender addresses (not local-parts) which are |
| 339 | known to be valid from the sending domain: the usual sender |
| 340 | verification is skipped for such addresses. This is a hack for |
| 341 | sending domains which have misconfigured MX records. |
| 342 | |
| 343 | + service :: If true (the default if an entry is found) , then we |
| 344 | provide main mail service for this domain. |
| 345 | |
| 346 | + spam-check :: If true, then check incoming mail to this domain for |
| 347 | spam. Only overridden for special effects. |
| 348 | |
| 349 | + spam-limit-file :: The name of a file in =nwildlsearch= format in |
| 350 | which to look up RECIPIENT/SENDER to find a spam-score limit for a |
| 351 | message sent to the virtual domain. |
| 352 | |
| 353 | + spam-limit-userv :: The name of a user whose =exim-spam-limit= Userv |
| 354 | service should be invoked to find the spam-score limit for a message |
| 355 | sent to the virtual domain. |
| 356 | |
| 357 | + sysusers :: If true, then mail can be delivered to general system |
| 358 | users. Local part suffixes are supported, as for the primary |
| 359 | domain. Spam limit customization can be done in the usual way. |
| 360 | Users can opt into virtual hosts by writing a |
| 361 | =~/.mail/forward.vhost=. |
| 362 | |
| 363 | + tls-certificate :: The name (subject to expansion) of a file |
| 364 | containing the TLS client certificate list to present when sending |
| 365 | mail to this domain. Requires a *route* entry for the target |
| 366 | domain. |
| 367 | |
| 368 | + tls-ciphers :: A list (subject to expansion) of permitted |
| 369 | ciphersuite names when delivering mail to this domain. |
| 370 | Alternatively, this can be one of the special keywords *good* or |
| 371 | *any*, for the preconfigured known-strong and any-acceptable lists. |
| 372 | Requires a *route* entry for the target domain. |
| 373 | |
| 374 | + tls-min-dh-bits :: When routing to this domain, ensure that the |
| 375 | order of the Diffie--Hellman group used for forward-secure key |
| 376 | exchange has at least this many bits. Because the Exim |
| 377 | =tls_dh_min_bits= option doesn't actually allow expansion, only |
| 378 | *1024* and *2048* are valid values for this option. Requires a |
| 379 | *route* entry for the target domain. |
| 380 | |
| 381 | + tls-peer-ca :: The name (subject to expansion) of a file containing |
| 382 | acceptable trust anchors for verifying the server's certificate when |
| 383 | delivering to this domain (and to require TLS for the |
| 384 | communication). The default is to not worry about TLS. Requires a |
| 385 | *route* entry for the target domain. |
| 386 | |
| 387 | + tls-private-key :: The name (subject to expansion) of a file |
| 388 | containing the private key to use to authenticate to a server when |
| 389 | delivering to this domain. Requires a *route* entry for the domain. |
| 390 | |
| 391 | + users :: A list (subject to expansion) of user names (matched as |
| 392 | local parts) of users who are permitted to send mail from this |
| 393 | domain. |
| 394 | |
| 395 | |
| 396 | ** =helo.conf= |
| 397 | |
| 398 | This file is a =partial0-lsearch=-format map from HELO names to |
| 399 | =match_ip= lists of IP addresses which are permitted to claim that name. |
| 400 | This is intended to deal with hosts whose DNS configuration doesn't |
| 401 | match their HELO announcement. |
| 402 | |
| 403 | * COMMENT Emacs cruft |
| 404 | |
| 405 | #+LaTeX_CLASS: strayman |
| 406 | |
| 407 | ### Local variables: |
| 408 | ### mode: org |
| 409 | ### End: |