Merge branch 'next' of ssh://down.oryx.com/oryx/aox into next
[aox:aox.git] / notes
1 Schedule
2
3   AMS: 04/28–05/12: Munsiari.
4
5   Welcome back, Abhijit.
6
7
8 P/W: Stuff we may want to keep
9
10   List::take()->remove() was good
11
12   also keeping iterators working
13
14   Scope
15
16   Having EH make a new Log by default
17
18   Simplifying the way Connection objects are added to the main loop
19
20   List::append( List ) -> appendList()
21
22   smtpclient has simpler logic... but don't break what works
23
24   cancelQuery rewrite. not sure.
25
26   Do (some of) these, one at a time, making sure nothing breaks after
27   each one. None soon.
28
29
30 3.1.2: 2009-05-xx
31
32   Bugfixes.
33
34   Something about pg_toast perhaps.
35
36   Add stuff so retention policies can be deleted
37
38
39 Functions and views
40
41   Views that'll be good for people:
42   - Valid local email addresses and users
43   - Sender information
44     - How many earlier messages from that address
45     - How many messages to that address
46     - How many earlier messages to/from the domain
47
48   Functions:
49   - Create user
50   - Delete user
51   - Rename user
52   - Change password
53   - Change password, given old and new password, checking
54   - Enable/disable alias
55   - Add/delete/rename alias
56
57
58 Release cycle
59
60   Five weeks, t-35 to t (a Monday).
61
62   t-38: we decide on a feature list for the release.
63
64   t-14: Whatever hasn't been started is dropped, whatever cannot be
65   completed before t-7 is laid aside for the next release. Write the
66   announcement text.
67
68   t-7: Fork the release and remove any code that needs to be removed.
69
70   t-4: Roll the tarball and do the release chores.
71
72   t-3: See t-38 above.
73
74   t-0: A crontab does what it needs to do.
75
76
77 The value of features
78
79   Archiveopteryx provides online archiving. We want the features we
80   add to improve one or more of these:
81   - adding mail to the archive
82   - accessing the archive
83   - managing the archive
84
85   For nontechnical reasons I add a fourth goal:
86   - making current users happy
87
88   Each new feature should help in some way; the new features that help
89   the most are the ones we need most (in the long term - in the short
90   term we also need to help existing users).
91
92
93 The next eight months
94
95   - Message retention
96       User interface
97       Message identification
98       Logging changes to the message
99   - aoximport improvements
100   - Full text search
101   - More documentation
102       aox operations guide
103       best practice papers
104   - Better documentation
105   - VIEW improvements
106       INTHREAD
107       multi-mailbox searches
108       miscellaneous
109   - Account management
110       ACL management
111       VIEW management
112   - Recording the fate of outgoing mail
113   - Proper full-text searching
114   - Better exploratory search
115   - Useful webmail
116   - Address search
117       Web UI
118       IMAP X-extension
119       Exporting to addressbooks
120   - Monitoring
121       Graphing
122
123
124 Installer doesn't take steps to ensure that the installation is usable
125
126   It could do at least two things:
127
128   Run all the same checks on the new installation as 'aox check' and
129   archiveopteryx at startup.
130
131   Try to connect to all the server addresses and if anything's
132   listening anywhere, mention it on stdout.
133
134   In addition to this, the installer does the wrong thing right now if
135   it creates the database users and then fails to run psql to load the
136   schema. It exits with an error, which means the randomly-generated
137   passwords are lost, because the configuration file is not written.
138
139
140 db-address=localhost works, but needs improvement.
141
142   - A new connect(addr, port) function resolves the given address and
143     creates one SerialConnector object for each result. It starts the
144     first one, which (after an error, or a delay of 1s) initiates the
145     next connection in line and so on. The first one to connect swaps
146     out the d of the original connection with its own, and makes the
147     EventLoop act as though it had just connected.
148
149   It works, but the code is a little ugly. The error handling logic
150   needs a careful look after some time. Once that's solid, the other
151   callers (SpoolManager/SmtpClient etc.) can be converted.
152
153
154 aox check schema
155
156   This command would check several things.
157
158   a) that dbuser has the needed rights
159   b) that all the right tables are there, and all the right columns,
160      with the right types, and no unexpected constraints
161   c) that all the right indexes are there
162   d) that dbowner owns everything
163   i) that inserts that would duplicate a constraint are properly
164      recognised
165
166   As a bonus, perhaps it could list some unexpected/unknown deviations:
167   e) locally added tables
168   f) locally added columns
169   g) locally added indices
170   h) missing constraints
171
172   Change 43939 and following move towards this: the idea is to
173   introduce new functions e.g. Schema::checkIntegrity (in addition to
174   checkRevision) and Schema::grantPrivileges, that can be used both by
175   aox check schema/aox grant privileges/whatever, and also by the
176   installer (instead of lib/grant-privileges, and instead of the
177   half-hearted checking it does now). the server is essentially
178   unaffected, it just uses Database::checkSchema/checkAccess for a
179   quick check.
180
181   this sounds ok, but it's ugly because Schema::execute is completely
182   given to upgrading the schema, and neither can nor should be
183   repurposed to do other things besides. so that means more static
184   functions in Schema and separate EventHandlers to do the
185   checking/granting/whatevering. but that's okay.
186
187
188 Items for web site
189
190   In addition to stuff in the operations guide:
191
192   - List/description of IMAP/POP/SMTP extensions
193   - RFC pages
194   - man pages (old ones too)
195   - Source documentation
196   - Best practices
197   - FAQ
198   - Version-specific pages
199   - Download-specific pages
200   - Client-specific pages
201
202
203 Various TODO items from earlier releases.
204
205   Message retention policy
206
207   - Soft-quota/archival stuff too?
208   - Message arrival tag (for archiving)
209
210   Miscellaneous:
211
212   - Database replication support (local mirror)
213
214   THREAD?
215
216   Basic administration using the httpd
217
218   Indexing for DOC bodyparts
219
220   aox backup/restore (or similarly helpful procedure)
221
222
223 The \Answered flag
224
225   We could add a little code to help that flag.
226
227   1. Disallow clearing it once set.
228   2. Set it on messages when we see an outgoing reply.
229
230   This would make it easier to force archiving.
231
232
233 5255
234
235   We already inplement I18NLEVEL=1, so I advertised that. I18NLEVEL=2
236   doesn't seem very useful. I also don't know how to do that in SQL.
237
238
239 Other RFCs
240
241   I think we need to consider these RFCs, or at least mention them
242   somewhere in the documentation so we know we've considered them:
243
244   821
245   934  (?)
246   974
247   1049 (should be handled fine, so check and mention)
248   1641 (old mime?)
249   1731 (old imap?)
250   1893 (ditto)
251   1894 (older version of something we handle, right?)
252   2044 (?)
253   2068 (HTTP? surely we do that)
254   2222
255   2244
256
257
258 Cleartext passwords
259
260   We help migrating away from cleartext/plaintext passwords:
261
262   1. We also store SCRAM and similar secrets in the DB (secrets which
263      aren't password equivalents)
264   2. We extend the users table with two new columns, 'last time
265      cleartext was needed' and 'number of successful authentications
266      without cleartext password usage since cleartext'.
267   3. If a client uses SCRAM, we increment the counter.
268   4. If a client uses CRAM or PLAIN, we reset counter and set the time
269      to today.
270   5. We provide some helping code to delete passwords for users with a
271      high count and a long-ago time.
272   6. We add documentation saying that if you disable auth-this and
273      auth-that, you can disable store-plaintext-passwords.
274   7. We add configuration/db sanity checks for ditto.
275
276
277 Database schema range
278
279   People occasionally need to access the db with an old version of
280   mailstore. I suggest that we:
281
282   a) add a 'writable_from' column specifying the oldest version that
283      can write to the database.
284   b) add a 'readable_from' column specifying the oldest version that
285      can read the database
286
287   aox upgrade schema would update writable_from to the oldest schema
288   version for which a writer would do the right job. This would often
289   change when a table changes, but not when a table is added.
290
291   readable_from would be the oldest revision that can read the database.
292
293   When the server starts up, it would check:
294
295   - am I >writable_from? If so, mailboxes can be read-write
296   - else, am I >readable_from? If so, startup can proceed, but all
297     mailboxes are read-only. lmtp, smtp and smtp-submit do not start.
298   - else, quit.
299
300   And in order to handle database updates, I suggest another table,
301   'features', with a single string column. When aox update database
302   fixes something, it inserts a row into features. A modern database
303   would have two rows in this table, 'numbered address fields' and 'no
304   nulls in bodyparts'.
305
306
307 Sieve
308
309   Alexey suggests the following extensions (in the following order):
310   Vacation, reject, imapflags, subaddress.
311
312   We still haven't done imapflags.
313
314
315 Reject or ereject may want MDNs instead of DSNs
316
317   Our sieve code generates DSNs if it can't generate protocol-level
318   refusal, which it always can in practice. MDNs should be used in at
319   least some cases, if a non-zero percentage of zero can be considered
320   "some cases".
321
322
323 RFCs 2852 and 4865
324
325   Easy to do once we have port 587; we need to set the start and end
326   columns right, that's about it.
327
328
329 Message tracking
330
331   RFCs 3885-8 specify ways to track messages that have been sent. We
332   can implement that fairly easily.
333
334   If we route outgoing mail via a smarthost, that smarthost has to
335   support MTRK in order for tracking to work well.
336
337   We can track mail provided that at least one of these is true:
338
339   - we deliver directly to the end server (we don't know whether
340     that's the case, though)
341
342   - we deliver via an MTRK-capable server
343
344   - we deliver into our own database
345
346   Sounds likely to be true maybe 80-90% of the time.
347
348   If none are true, we can at least say, easily, where we delivered,
349   when, and why.
350
351   We could implement the tracking protocol (and I'd write a query blah
352   in mailchen), and also provide a query interface via the web.
353
354
355 Message tracking 2
356
357   We can recognize the ESMTP id for the most common MTAs. Postfix says:
358
359     250 Ok: queued as D1A324AC85
360
361   Sendmail and exim surely say something similar. We could keep that ID
362   in delivery_recipients and use it in DSNs.
363
364
365 Generating bounces
366
367   Our bounces would look better if they included the entire SMTP
368   conversation (starting with RSET or EHLO).
369
370
371 Bounces and DSNs
372
373   Mail is currently fairly reliable. There is one big exception:
374   Bounces aren't 100% parsable. But generally, if you work hard, you
375   can know whether a message was delivered or not, and mostly they are
376   delivered.
377
378   So we benefit from converting the most common nonstandard bounces to
379   DSNs, and then treat them as DSNs.
380
381   For nonstandard bounces (like those of qmail) we identify the
382   message by trying hard, do some hacky parsing, use the bounce
383   (excluding trailing message) as first part of the DSN multipart,
384   cook up a new DSN report based on the parsing, and save
385   text/822-headers as a third part.
386
387   Then, searches that tie bounces together with messages sent work
388   even better.
389
390   (Another trick we can/should use is to see whether the host we
391   deliver to seems to be the final destination based on earlier
392   (answered) messages.)
393
394
395 Memory use for common operations
396
397   Some use _vastly_ too much memory. I saw a single IMAP FETCH for a
398   mere 4200 messages use 173MB yesterday. (Later note: This should be
399   gone, gone, gone, but it would still be good to check that these
400   problems don't reappear, reappear, reappear.)
401
402   The most elegant way to solve that would be to supervise memory
403   usage for a known sequence. Inject these ten thousand messages,
404   check memory use (via the grapher), connect to the imap port run
405   this and that, check again, connect to the imap port run this and
406   that, check again, connect to the imap port run this and that, check
407   again... just a bunch of checks. Ignore output.
408
409
410 RFC 2554
411
412   Have to look closer at that, I hadn't grasped the MAIL FROM AUTH
413   issue and there may be more.
414
415   addParams( "auth", ... ) in MAIL FROM needs consideration. Not
416   important.
417
418
419 imapd/handlers/acl.cpp
420
421   Different tasks, some shared code, same file. Separate this out into
422   different classes inheriting something. Then add the right sort of
423   logging statement to the end of parse().
424
425
426 Threads in Archiveopteryx 4.0
427
428   I'm growing more and more fond of using a few threads, and not using
429   server-processes any more.  We'd replace server-processes with
430   server-threads, or just keep the name.
431
432   The core event loop would create a queue of work to be done based on
433   which file descriptors have input, and worker threads would take a
434   piece of work, obtain the fd's lock, and do it.
435
436   The Query would have a optional Connection pointer, the Transaction
437   would have a mandatory one. Scope would probably have one. Perhaps
438   Q+T could copy Scope's. A worker thread which processes database
439   input would have to obtain the lock for the scope's fd whenever it
440   enters the scope.
441
442   We'd be able to collect garbage without halts. Large IMAP Fetch
443   commands would also not cause halts. We'd be able to serve all
444   clients fairly, using all cores, using fewer database backends than
445   with server-processes.
446
447   The Apple Autozone GC looks good for this.
448
449   The default for server-processes ought to change to match the number
450   of processors:
451
452     Linux, Solaris, & AIX (per comments):
453         numCPU = sysconf( _SC_NPROCESSORS_ONLN );
454
455     FreeBSD, macosx, NetBSD, OpenBSD, etc.: 
456         int mib[4];
457         size_t len; 
458         
459         /* set the mib for hw.ncpu */
460         mib[0] = CTL_HW;
461         mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;
462         
463         /* get the number of CPUs from the system */
464         sysctl(mib, 2, &numCPU, &len, NULL, 0);
465         
466         if( numCPU < 1 ) 
467         {
468              mib[1] = HW_NCPU;
469              sysctl( mib, 2, &numCPU, &len, NULL, 0 );
470         
471              if( numCPU < 1 )
472                   numCPU = 1;
473         }
474
475
476 Full-text search
477
478   There Be Problems.
479
480   The code now assumes that the IMAP client searches for one or more
481   words, rather than an arbitrary substring. Postgres uses word
482   segmentation.
483
484   If postgres were to use e.g. overlapping three-letter languageless
485   substrings, we would do what IMAP wants. sounds senseless.
486
487   We also have a requirement to stem search arguments less.
488   Specifically, a search for ARM7TDMI should not return messages about
489   the ARM6 or about my left arm.
490
491
492 Convert more parsers to use AbnfParser
493
494   There are still a few places where we roll our own messy parsers and
495   suffer for it (e.g. HTTP, DigestMD5). We know they work, but making
496   them use AbnfParser in a spare moment would be an act of kindness.
497
498
499 aox/conf/tls-certificate
500
501   Those variables are not well described. We need a bit more.
502
503   Also, -secret is probably misnamed, we use -password for other
504   cases. I expect that's why aox show cf tls-certificate-secret yields
505   while e.g. aox show cf db-password does not.
506
507
508 METADATA
509
510   Needed for lemonade, as easy as annotate.
511
512
513 Autoresponder
514
515   We have vacation now, but it isn't quite right for autoresponses.
516   Sieve autorespond should be like this:
517
518   1. :quote should quote the first text/plain part if all of the
519      following are true:
520
521      1. The message is signed, and the signature verified (using any
522         supported signature mechanism, DKIM SHOULD be supported).
523      2. The first text/plain part does not have a Content-Disposition
524         other than inline.
525
526      If any of the conditions aren't true, :quote shouldn't quote.
527
528      If there's a signature block, :quote shouldn't quote that.
529
530      If the quoted text would be more than ten lines, :quote may crop
531      it down as much as it wants, ideally by skipping lines starting
532      with '>', otherwise by removing the last lines.
533
534   2. :subject, :from and :addresses as for vacation.
535
536   3. :cc can be used to send a copy to the specified From address.
537
538   4. The default :handle should not be based on the quoted text.
539
540   5. Two text arguments, one for text before the quoted text, one for
541      text after the quoted text.
542
543   6. The autoresponse goes to the envelope sender, as some RFC
544      requires. So we want an option to skip the response unless the
545      return-path matches reply-to (if present) or From (unless
546      reply-to is present).
547
548
549 Message arrival tag
550
551   Once annotate is done, we want a tag, ie. a magic annotation which
552   stays glued to the message wherever it goes, even after copy/move.
553
554   We also want a way to store the original RFC822 format somewhere
555   inside and/or outside the database, indexed by the arrival tag
556   identifier. It's good if the tag is split, so we can have "x-y"
557   where X is the CD/DVD number and Y is the file on the CD/DVD. Or
558   something like that.
559
560
561 Sieve ihave
562
563   There are three holes in our ihave rules.
564
565   Single-child anyof doesn't promote the ihave:
566
567     if anyof( ihave "foo" ) {
568         foo; # errors should not be reported here
569     }
570
571   Not doesn't promote:
572
573     if not not ihave "foo" {
574         foo; # errors should not be reported here
575     }
576
577   Finally, if/elsif always applies the ihave to its own block, instead
578   of walking along elsif/else to find the block that might be executed
579   if ihave returns true:
580
581     if not ihave "foo" {
582         # errors should be reported here
583     } else {
584         foo; # but not here
585     }
586
587
588 C/R
589
590   C/R sucks. But it has its uses, so we can benefit from implementing
591   it somehow. Here are some classes of messages we may want to treat
592   specially:
593
594   - replies to own mail
595   - messages in languages not understood by the user
596   - mail from previously unknown addresses
597   - mail from freemail providers
598   - vacation responses from unknowns
599   - messages likely, but not certain to be out-of-office-autoreply
600   - dkim/mass-signed messages (if verified)
601
602   The questions are: How can we ensure that we almost never challenge
603   real mail, while simultaneously challenging most/all messages that
604   don't come from valid senders? How can we provide suitable
605   configuration?
606
607   Mail from freemail vendors tends to have a "Received: ... via HTT"
608   field.
609
610
611 Squirrelmail
612
613   Inefficiency has a name.
614
615   1. Too many LOGINs. We can cache Users using a Cache, that'll solve
616      that. But LOGIN isn't that slow, so I'm not sure it's worth it.
617
618   2. Too many SELECTs and EXAMINEs. SessionCAche and FirstUnreadCache
619      solve that.
620
621   3. Too many EXPUNGEs. If we keep a "last expunged at modseq" in
622      ImapSession, check and set it in Expunge, and check and set it in
623      store ("if the last expunge was the previous modseq, and I'm not
624      adding any \deleted flags, then increase"), then we can turn
625      those expunges into noops.
626
627   That should speed up SM and probably other webmail systems nicely.
628
629
630 Using rrdtool
631
632   What could we want to graph with rrdtool? Lots.
633
634   - CPU seconds used
635   - database size
636   - messages in the db
637   - average response time
638   - 95th percentile response time
639   - messages per user
640   - message size per user
641   - average query execution time
642   - average query queue size
643
644   More?
645
646   http://jwatt.org/svg/authoring/ is interesting for generating graphs
647   via the web interface.
648
649
650 Box features
651
652   1. web ui to set up view mailboxes (and to search the archive
653      generally)
654
655   2. web ui to configure sieve
656
657   3. web administration, to add users, etc.
658
659   4. i18n for all web-accessible anythings, and after that, for aox.
660
661   5. rrd stuff available next to aox in the boxes, perhaps nagios
662      stuff too
663
664
665 SASL NTLM authentication
666
667   It may be odd and undocumented, and it may not be as strong as
668   DIGEST-MD5, but it's implemented in Certain Clients ;)
669
670   http://www.innovation.ch/java/ntlm.html seems to be a reasonable
671   description. Cyrus also implements it.
672
673   http://davenport.sourceforge.net/ntlm.html ?
674
675
676 Split the folder view into pages.
677
678   Need to decide on what a page is. "Most recent 25 threads" is a
679   slippery concept when a new thread is created between page views.
680
681   One probably good way: Use "after" and "before", so "next" would
682   point to "most recent 25 threads after the last one on this
683   page". Doable, not bad, and with the aid if a new Session subclass
684   we can even include a note when there's new activity.
685
686
687 We should be able to use a read-only local database mirror.
688
689   That way, we can play nicely with most replication systems.
690
691   The way to do it: add a new db-mirror setting pointing to a
692   read-only database mirror. all queries that update are sent to
693   db-address, all selects are sent to db-mirror. db-mirror defaults to
694   db-address.
695
696
697 We should test multipart/signed and multipart/encrypted support.
698
699   We must add a selection of RFC 1847 messages to canonical, and make
700   sure they survive the round trip. No doubt there will be bugs.
701
702
703 Per-user client certificates
704
705   We could store zero or more client certificates (or fingerprints, or
706   whatever) per user. When a user has logged in, we'd check whether
707   that user has a non-zero list of certificates, and if so, we'd do a
708   TLS renegotiation, this time demanding a client certificate. If the
709   client certificate matches, we allow access, otherwise we don't (and
710   we alert the user).
711
712   A bit difficult to do with the hands-off tlsproxy.
713
714
715 We should store bodyparts.text for PDF/DOC.
716
717   We need non-GPLed code to convert PDF and DOC to plaintext.
718
719   Or maybe we need a generic interface to talk to plugins.
720
721
722 Switch to using named constraints everywhere.
723
724
725 Default c-t-e of PGP signatures
726
727   Right now we give them binary. q-p or 7bit would be better, I think.
728
729   What other application/* types are really text?
730
731   From a conversation the other day: we could avoid base64 encoding an
732   entity whose content-type is not text if it contains only printable
733   ASCII. I don't know if it's worth doing, though.
734
735   The problem with doing that is that it treats sequences of CR LF, CR
736   and LF as equivalent. An application/foobar object that happens to
737   contain only CR, LF and printable ASCII can be broken.
738
739
740 Recognising spam
741
742   The good spam filters now all seem to require local training with
743   both spam and nonspam corpora. We can do clever stuff... sometimes.
744
745   Instead of filtering at delivery, we can filter when a message
746   becomes \recent. When we increase first_recent, we hand each new
747   message to the categoriser, and set $Spam or $Nonspam based on its
748   answer.
749
750   This lets the categoriser use all the information that's available
751   right up to the moment the user looks at his mail.
752
753   We can also build corpora for training easily. All messages to which
754   users have replied are nonspam, replies to messages from local users
755   are nonspam, messages in certain folders are spam, messages with a
756   certain flag are spam.
757
758   We can connect to a local server to ask whether a message is spam.
759   They seem to work that way, but with n different protocols.
760
761
762 TLS client support (smtp, postgresql)
763
764
765 "Writing Secure Code"
766
767   We have a page about security, /mailstore/security.html, and a
768   section of the mailstore.7 man page mentions it too.
769
770   We need to look at ISBN 0735617228 and improve security.html with
771   points from it. It could also be that we'll improve the code itself.
772
773
774 Play with PITR and write /ams/pitr.html
775
776
777 Document IPC structure
778
779   Some man page, or some web page, or both, should say who's
780   connecting to who and why.
781
782
783 Add a web page about the charset encoding.
784
785   It's a novel and good algorithm, so we can make a good page about
786   it. We also can link to data sources there.
787
788   The documentation for Codec::byString() should mention that page's
789   URL.
790
791
792 Make a web page about our licensing
793
794   Not sure what to say there. the purpose of the page would be to
795   direct people to one of the two others, really. and to be linked to
796   from the home page.
797
798
799 The "Database" link on home page
800
801   Where should it go? People might click it wondering why to use a
802   database instead of flat files and wanting to know what we do with
803   databases.
804
805
806 Search ourselves, not via google
807
808   Or maybe farm that out, get google to search with an approximation
809   of our design. http://www.google.com/faq_freewebsearch.html may be
810   interesting.
811
812
813 Logging to syslog
814
815   The logd HUP handler can switch to syslog if it can't reopen the
816   logfile instead of exiting.
817
818
819 Rendering webmail HTML is presumably good, but...
820
821   We have a potential security hole: A malevolent HTML bodypart is
822   forwarded as is on the "download bodypart" page.
823
824   See http://ha.ckers.org/xss.html
825
826
827 Faster mapping from unicode to 8-bit encodings
828
829   At the moment, we use a while loop to find the right codepoint in an
830   array[256]. Mapping U+00EF to latin-1 requires looping from 0 to
831   0xEF, checking those 239 entries.
832
833   We could use a DAG of partial mappings to make it faster. Much
834   faster. Mapping U+20AC to 8895-15 would require just one lookup: In
835   the first partial table for 8859-15. Mapping U+0065 to 8859-15 would
836   require three: In the first (U+20AC, one entry long), in the
837   fallback (U+00A0, 96 entries long) and in the last (U+0000, 160
838   entries long).
839
840   Effectively, 8859-15 would be a first table of exceptions and then
841   fall back to 8859-1.
842
843   The tables could be built automatically, compiled in, and would be
844   tested by our existing apparatus.
845
846   Or we could do it simpler and perhaps even faster: Make a local
847   array from unicode to target at the start, fill it in as we go, and
848   do the slow scan only when we see a codepoint for the first time.
849
850
851 Multipart/signed automatic processing
852
853   We could check signatures automatically on delivery, and reject bad
854   signed messages.
855
856   The big benefit is that some forgeries are rejected, even though the
857   reader and the reading MUA doesn't do anything different.
858
859   The disadvantage is that we (probably?) can't verify all signatures,
860   which gives a false sense of security for the undetectable forgeries.
861
862   In case of PKCS7, it's possible to self-sign. Those we cannot
863   check. In that case we remove the signature entirely from the MIME
864   structure, so it doesn't look checked to the end-user.
865
866   PGP cannot be checked, except it sort of can. We can have a small
867   default keyring including the heise.de CA key and so on, and treat
868   that as root CAs, using the keyservers to dig up intermediate keys.
869
870
871 PGP automatic processing
872
873   Apparently there are five different PGP wrapping formats. We could
874   detect four and transform them to the proper MIME format.
875
876
877 Plugins
878
879   It's not given that we want to accept all mail. If we don't, who
880   makes the decision? A sieve script may, and refuse/reject mail it
881   does not like. And a little bit of pluginnery may. I think we'd do
882   well to support the postfix plugin protocol, so all postfix policy
883   servers can work with aox. (All? Or just half? Doesn't postfix have
884   two types of policy plugins?)
885
886   We may even support site-wide and group-wide sieve scripts and
887   permit a sieve script to invoke the plugin. A sieve statement like
888   this?
889
890      UsePolicyServer localhost 10023 ;
891
892
893 BURL
894
895   If the message is multipart and the boundary occurs in a part, that
896   part needs encoding. Or else switch to a different body.
897
898
899 Cybertec replicator
900
901   Is it good? What are people saying about it? What should we do about it?
902
903   Ewald Geschwinde on IRC (the first time I've seen him; 2007-07-11) said:
904   *egeschwinde* When I have time I will test your product on our
905   multimaster cluster
906   *egeschwinde* maybe also on the queuing system
907
908
909 Delaying seen-flag setting
910
911   We can move the seenflagsetter to imapsession, build up flags to
912   set, flush the write cache before fetch flags, store, state-altering
913   commands and searches which use either modseq or flags.
914
915   This ought to cut down the number of transactions issued per imap
916   command nicely.
917
918
919 The web interface should offer a download link for attachments.
920
921   For patches attached as text/plain with the right Content-Disposition,
922   for example.
923
924
925 Sending forged From despite check-sender-addresses
926
927   vacation :from and notify :mailto :from don't check
928
929   The injector probably needs to get the logic from the smtp server.
930
931
932 Per-group and systemwide sieves
933
934   People always seem to want such things. It'll be easy to implement.
935   Most of the tricky issues are described in
936   http://tools.ietf.org/html/draft-degener-sieve-multiscript-00
937
938
939 The Sieve "header" test may fail
940
941   Write a test or three that feeds the thing a 2047-encoded header
942   field and checks that it's correctly matched/not matched. Then make
943   it pass.
944
945
946 The subaddress specification says foo@ != foo+@ wrt. :detail
947
948   The former causes any :detail tests to evaluate to false, while the
949   latter treats :detail as an empty string. We treat both as an empty
950   string.
951
952   (We could set detail to a single null byte, to \0\r\0\n\0, to a
953   sequence of private-use unicode characters, or even to
954   Entropy::string( 8 ) if there is no separator. The chance of that
955   appearing in an address is negligible.)
956
957
958 Distribution packages
959
960   - RPM: silug has offered to help.
961   - FreeBSD port: devin (Tod McQuillin) has offered to help.
962   - Debian: ? (license problems, but we could provide a .deb).
963   - Ubuntu: ?
964
965
966 SMTP extensions
967
968   Here are the ones we still don't implement, but ought to implement
969   at some point:
970
971   SUBMITTER? perhaps
972   DELIVERBY (RFC 2852): At some time.
973   FUTURERELEASE (RFC 4865): At some time.
974   MTRK: As soon as someone else does it.
975
976   http://www.iana.org/assignments/mail-parameters
977
978   DELIVERBY has the funny little characteristic that we can support it
979   with great ease iff the smarthost does, so we ought to advertise iff
980   if the smarthost does.
981
982
983 SUBMITTER
984
985   The work needed to support that:
986
987   1. Pass a submitter to SmtpClient.
988   2. Pass the sieve owner or logged-in user's address as submitter.
989   3. Send that as SUBMITTER= if the smarthost advertises SUBMITTER and
990      the submitter is different from mail-from.
991
992   4. Advertise SUBMITTER.
993   5. If the SMTP/LMTP/Submit client sends SUBMITTER and it's different
994      from the mail-from, record the address in Received.
995   6. If there's a sieve extension specifying how, push the submitter
996      into the envelope so the sieve can see it.
997
998   Easy peasy. But there's no value to offset this (small) cost, is
999   there? Maybe as a hack when one of us is fed up.
1000
1001
1002 The groups and group_members tables seem a little underused
1003
1004   We do not use them at all. We meant to use them for "advanced" ACL
1005   support, but nobody ever asked, and it didn't seem worthwhile.
1006
1007   I now think it's worthwhile.
1008
1009   Here's what I want to add:
1010
1011   Make a superusers group, which members can authenticate as anyone,
1012   and the notion of group admins, who can authenticate as other
1013   members of the group.
1014
1015   Or maybe an administrator table, linking a user to either a group or
1016   to null. If a group, then the admin can authenticate as other
1017   members of that group and (importantly) has 'a' right on their
1018   mailboxes, if null, then ditto for all groups.
1019
1020   Extend Permissions to link against group_members when selecting
1021   applicable permissions.
1022
1023   Make groups be permissible ACL identifiers.
1024
1025
1026 We need to be able to disable users
1027
1028   - Reject mail with 5xx/4xx.
1029   - Prevent login.
1030   - 1+2.
1031   - a group admin can enable/disable group members
1032   - a superadmin can enable/disable anyone
1033   - a group admin cannot unblock an overall blockage
1034
1035
1036 Showing email addresses in public archives is... well...
1037
1038   There are three common solutions:
1039
1040   1. Show the address. What we do now. Gives addresses to spammers,
1041      which is undesirable.
1042
1043   2. Replace @ with at or some other easily reversible change. I
1044      assume gigamega.com, litefinder.net and other address scrapers
1045      already detect the common obfuscations, so this is pointless.
1046
1047   3. Show part of the address, e.g. arnt@ory... or
1048      ar...@oryx.co... for arnt@oryx.com. Isn't reversible, so the
1049      spammers can't undo it, but also makes the archive less usable
1050      for people.
1051
1052   We might change to 3, but with a captcha-protected option to show
1053   1. That would give us all the advantages and no serious disadvantage.
1054   But we would have to implement captchas somehow, which would be a
1055   moderate pain.
1056
1057
1058 aox.org/badmail/
1059
1060   Explain that aox can't store everything, why not (in short), that it
1061   has many workarounds and point to examples/, how to detect/report
1062   bad messages and how to fix things with reparse. Point to
1063   /aox/reparse for more detail.
1064
1065   Subpages:
1066
1067   badmail/examples/n for 1<=n<=8, with good and bad blah, generated
1068   from chosen canonicals, to show how we fix things up. Each page
1069   showing old and new, with differences indicated, and they should be
1070   ordered from reasonable/common to outrageous.
1071
1072   badmail/examples/ summing up 1-8 and giving one or two truly
1073   hopeless cases. The hopeless case(s) should also be shown in
1074   anonymised form.
1075
1076   badmail/examples/comparison if I feel nasty and bored one day,
1077   showing how a few IMAP servers handle messages 1-8 and the
1078   impossible one(s). Does "fetch envelope" return the right thing?
1079   "fetch bodystructure"? Some choice searches? We don't want to link
1080   to this page very much. It gets a fine <table> containing many/few
1081   &#x2713; cells.
1082
1083   Possibly we want to include screenshots showing how Thunderbird or
1084   another GUI client that uses envelope/bodystructure renders a
1085   mailbox containing 1-8. Screenshots using aox and using another
1086   server, one that gets few &#x2713; cells in the table. I'm not sure
1087   where to link to these screenshots. Apple Mail?
1088
1089   We also need aox.org/aox/reparse and I suppose other /aox/<command>
1090   pages.
1091
1092
1093 Some unfortunate logging
1094
1095   This is the tail end of a connection Thunderbird used to save
1096   something to the Sent folder, rewrapped for easier reading:
1097
1098     imap/info: 2/1/1/2442/6: 2008-06-18 12:53:54.109
1099         Execution time 550ms
1100     imap/debug: 2/1/1/2442/6: 2008-06-18 12:53:54.109
1101         Finished
1102     imap/debug: 2/1/1/2442: 2008-06-18 12:53:54.109
1103         IMAP::runCommands, 1 commands
1104     imap/info: 2/1/1/2442/6: 2008-06-18 12:53:54.109
1105         Result: OK [APPENDUID 19] done
1106     imap/debug: 2/1/1/2442/6: 2008-06-18 12:53:54.110
1107         Retired
1108     imap/debug: 2/1/1/2442: 2008-06-18 12:53:54.110
1109         IMAP::runCommands, 0 commands
1110     imap/info: 2/1/1/2442: 2008-06-18 13:23:53.458
1111         Idle timeout
1112     imap/debug: 2/1/1/2442: 2008-06-18 13:23:53.459
1113         Closing: IMAP server 195.30.37.30:143
1114                  connected to client 195.30.37.9:52209, on fd 26
1115     imap/debug: 2/1/1/2442: 2008-06-18 13:23:53.459
1116         IMAP::runCommands, 0 commands
1117     imap/debug: 2/1/1/2442: 2008-06-18 13:23:53.459
1118         IMAP::runCommands, 0 commands
1119     imap/info: 2/1/1/2442: 2008-06-18 13:23:53.459
1120         Unexpected close by client
1121     imap/debug: 2/1/1/2442: 2008-06-18 13:23:53.459
1122         IMAP::runCommands, 0 commands
1123     general/debug: 2/1/1/2442/2/2/2: 2008-06-18 13:23:53.461
1124         Closing: Byte forwarder 127.0.0.1:56695
1125                  connected to client 127.0.0.1:2061, on fd 27
1126     general/info: 2/1/1/2442/2/2/2: 2008-06-18 13:23:53.461
1127         Shutting down byte forwarder due to peer close.
1128     imap/info: 2/1/1/2442: 2008-06-18 13:23:53.464
1129         Unexpected close by client
1130     imap/debug: 2/1/1/2442: 2008-06-18 13:23:53.464
1131         IMAP::runCommands, 0 commands
1132
1133   Hardly unexpected. Will fix later, not sure how.
1134
1135
1136 Dynamically preparing often-used queries
1137
1138   We can prepare queries cleverly.
1139
1140   Inside Query, at submit time, we first check whether a Query's text
1141   matches a PreparedStatement, and uses it if so.
1142
1143   If not, we check whether the query looks preparable. The condition
1144   seems to be simple: Starts with 'select ' and contains no numbers.
1145   If it's preparable we add it to a cache, which is discarded at GC
1146   time.
1147
1148   If a preparable query is used more than n times before the cache is
1149   discarded, we prepare the query and keep the PreparedStatement
1150   around.
1151
1152
1153 aox.org/clients/
1154
1155   Move the list of clients from /imap/ and /pop here. Make a per-client
1156   page, e.g. /clients/outlook, with notes.
1157
1158   1. Which protocols can you use? Usually IMAP+Submit.
1159
1160   2. Any bugs worth speaking of?
1161
1162   3. Any particular configuration advice? for /clients/outlook we say
1163      "enable use-smtps". For /clients/applemail we point to that IDLE
1164      plugin.
1165
1166   That's it, right?
1167
1168
1169 Defending against PGP Desktop and similar
1170
1171   There are several more things to do:
1172
1173   - Guess that it's repeating a query for smallish UID sets and do the
1174     query once and for all.
1175
1176   - Defend against 'OR BODY asdf BODY asd' by recognising in
1177     simplify() that when asd matches, asdf always will. Added bonus
1178     for the base64 shit.
1179
1180   - Hack in Search::parse() for that/those specific search keys, and
1181     setting up a more sensible selector.
1182
1183   The first two make sense IMO.
1184
1185
1186 SMS gateway
1187
1188   We want Archiveopteryx to work as installed. We want to support
1189   Sieve notify, including SMS.
1190
1191   I think that means Oryx needs to operate an Archiveopteryx->SMS
1192   gateway, allow people do send a few SMSes, and provide people with
1193   the ability to operate a gateway of their own.
1194
1195   There are many IP->SMS gateways in the world. Some free, but we
1196   don't want to use those, they're unreliable. Many paid for, those
1197   are reliable. Most of them work using HTTP requests: You POST a
1198   query with your credentials and the gateway reports.
1199
1200   So my plan is as follows:
1201
1202   1. Become a customer of someone like that.
1203
1204   2. Write a program which accepts requests in a format we define,
1205      forwards them in the HTTP-based format our provider uses, and
1206      relays the response back.
1207
1208   3. Provide that service to new Archiveopteryx installations, with
1209      limitations on use.
1210
1211   4. Provide the gateway program along with Archiveopteryx, so people
1212      can run it themselves.
1213
1214   I haven't thought of a good way to provide the service to
1215   Archiveopteryx users and weed out most other people.
1216
1217   Perhaps a better alternative: Automatically register with clickatell
1218   if SMS is enabled and not configured when it's first used. (But it's
1219   not possible to register with clickatell without intervention.)
1220
1221
1222 New RFCs
1223
1224   5463: sieve ihave
1225   5490: sieve metadata
1226
1227   5442: lemonade profile-bis
1228
1229
1230 Sieve notify
1231
1232   5435: sieve notify
1233   5436: sieve notify mailto
1234   5437: sieve notify xmpp
1235
1236   mailto: combined with :from is unchecked
1237
1238
1239 aox anonymise
1240
1241   1. An alias for anonymize
1242
1243   2. aox anonymise -a should make a set of cleartext.<n> and anon.<n>
1244      files in the current directory based on unparsed_messages, so
1245      it's easy to report everything to us.
1246   
1247
1248 Bug confusing U+ED00 and U+0000 in the message cache
1249
1250   When we write to the database, U+0000 (which occasionally occurs,
1251   mostly by mistake but sometimes on purpose) is transformed to
1252   U+ED00, and when we read it, back.
1253
1254   So if U+ED00 is written to the DB, it comes back as U+0000.
1255
1256   This means that Archiveopteryx works differently depending on
1257   whether the cache is used or not. That has to be resolved somehow.
1258
1259
1260 Axel, /Mime problem
1261
1262   The problem is that the VCF file contains literal NUL bytes, but is
1263   sent with a text/* MIME type, and we're mangling the NULs during
1264   charset conversion (or so I guess, given that they become '?'s
1265   instead).
1266
1267
1268 Various alias-related feature requests
1269
1270   e.g. Benjamin wants empty localparts, a number of people want multiple
1271   targets (Axel, Ingo).
1272
1273
1274 String::wrapped() vs. canonical 13
1275
1276   Arnt commented out some code which shouldn't have made i/13 fail, but
1277   did for him. Must investigate.
1278
1279
1280 Axel, /Unable to fetch 12MB mail
1281
1282   Some sort of loop in the fetcher? I didn't look.
1283
1284
1285 Axel, /2.10 status
1286
1287   Mail.app occasionally shows a panel, saying "SSL error: Identity of
1288   mail3.chaos1.de can't be verified, hit "continue" or "abort".
1289
1290
1291 Simon, /Segfault when accessing web-archive
1292
1293   Not looked yet, but probably the same as the one on archives. Will fix
1294   with the other known bugs.
1295
1296
1297 Caches that aren't
1298
1299   There's a session "cache" in HTTP.
1300
1301
1302 Mike Geiger's Thunderbird problems
1303
1304   TLS breakage (not yet reproduced) and copy-to-sent hanging.
1305
1306
1307 Problems found in 3.0.0 by Timo
1308
1309   - SEARCH SENTON/SENTBEFORE/SENTAFTER have some bugs.
1310     (Not verified because of segfault; will check later.)
1311
1312     Not fixed; I lean towards fixing it if it's the only thing
1313     imaptest complains about.
1314
1315
1316 Use current_setting('server_version_num') instead of parsing version()
1317
1318   (But only under 8.2+)
1319
1320
1321 HTML representation of selectors
1322
1323   We need:
1324
1325     - An HTML representation of selectors.
1326
1327       Should be easy to generate, display reasonably even without CSS,
1328       and easy to parse when we see it again.
1329
1330         <div id=1>
1331          <span class=selector>and 2 3</span>
1332          <span class=translated>Alle Begingungen müssen für jede Nachricht zutreffen</span>
1333          <div id=2>
1334           <span class=selector>header 4</span>
1335           <span class=translated>Headers enthalten <span id=4>arnt</span></span>
1336          </div>
1337          <div id=3>
1338           <span class=selector>body 5</span>
1339           <span class=translated>Körpertext enthält <span id=5>expunge</span></span>
1340          </div>
1341         </div>
1342
1343       (We don't want to parse translated text because of the ambiguity
1344       in mapping between texts and conditions if e.g. two conditions map
1345       to the same Bangla text. Hence the selector/translated split.)
1346
1347     - A parser to turn HTML into a selector; and a way to turn a
1348       selector into HTML (plus tests for the conversion).
1349
1350       We have HtmlParser.
1351
1352     - A component to display a view, and a component to edit a view
1353       (complete with evil Javascript) and a magic URL to accept the
1354       edited representation.
1355
1356
1357 Caching search results
1358
1359   If a selector is !dynamic(), its results can be cached until the next
1360   modseq change on the mailbox.
1361
1362
1363 Bugs
1364
1365   - "aox start" doesn't complain when there's a schema mismatch error.
1366   - aox -v -v is broken by the syslog change.
1367
1368
1369