1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
|
/* ========================================================================
* Copyright 1988-2006 University of Washington
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* ========================================================================
*/
Documentation of c-client Functions and Interfaces
REVISED: 19 August 1996
Credits
The original version of this document was written by Mark Crispin at
the University of Washington, and described the version of c-client that
supported the IMAP2 (RFC 1176) and IMAP2bis (unpublished) protocols.
This version is a substantial rewrite of that document, and was
written by Mark Crispin with funding from Sun Microsystems, Incorporated.
Sun's generous support of this work is gratefully acknowledged.
Road Map
This document is organized into the following sections. Except as
noted, an implementor of an application that uses c-client needs to be
familiar with all of these sections. Someone who plans to write a new
mailbox driver for c-client (or otherwise modify it) needs to be familiar
with all sections, no exception.
History
History of how c-client came about.
Overview
Read this before designing an application that uses c-client.
c-client Structures
Documentation of several important c-client structs which are
used in, and returned by, c-client calls.
String Structures
Documentation of the concept of a "string structure", which
provides random access to strings without requiring that the
string be in memory.
c-client Support Functions
Documentation of support functions for c-client; these deal
with c-client functionality.
Only mail_parameters() is of interest to most application
developers. Advanced application developers, particularly
for limited memory systems, may also need to know about the
readfn_t, mailgets_t, mailcache_t, and tcptimeout_t function
pointer types, and possibly also the mail_valid_net_parse()
function.
Mailbox Access Functions
Documentation of functions which deal with mailboxes;
listing, subscribing, creating, deleting, renaming, status
inquiries, opening, and closing mailboxes.
Handle Functions
Documentation of mail stream handles, which provide protection
for an advanced application which may have multiple pointers to
a single mail stream. If a stream has a handle on it, closing
the stream does not release its memory, so pointers to it in
the application remain valid. Freeing the last handle will free
the entire stream.
This is only of interest for advanced application developers.
Message Data Fetching Functions
Documentation on message data fetching in an open mailbox,
including parsed representations of RFC-822 and MIME headers
and message text. Also how to fetch message attributes (flags,
internal date, sizes).
Message Status Manipulation Functions
Documentation on altering message flags in an open mailbox.
Mailbox Searching
Documentation on searching an open mailbox for messages which
match certain criteria (e.g. "messages sent July 4 from Jones
with text `Paris'").
Miscellaneous Mailbox and Message Functions
Documentation on other operations that would be used by an
application but that don't fit into any of the above categories.
Date/Time Handling Functions
Documentation on functions that deal with date/time strings.
This is only of interest for advanced application developers
and for implementors of new c-client drivers.
Utility Functions
Documentation on internal utility functions.
This is primarily of interest for implementors of new c-client
drivers, but advanced application developers may also use some
of these functions.
Data Structure Instantiation/Destruction functions
Documentation on creating and destroy c-client structures.
This is primarily of interest for implementors of new c-client
drivers. However, application developers will need some of
these functions to create and destroy structures which are used
as arguments to various application functions.
Authentication Functions
Documentation on support for network protocol authentication
functions.
This is only of interest for implementors of new c-client
drivers which deal with authentication mechanisms.
Network Access Functions
Documentation on creating and destroy c-client structures.
This is primarily of interest for implementors of new c-client
drivers which deal with a network. However, advanced
application developers may need to use this information if they
wish to insert their own layer into a network session.
Subscription Management Functions
Documentation on managing the local (client-based) subscription
database file.
This is primarily of interest to advanced application developers.
Miscellaneous Utility Functions
Documentation on various useful utility functions, such as "make
a copy of this string."
SMTP Functions
Documentation on posting email messages via SMTP protocol.
NNTP Functions
Documentation on posting netnews messages via NNTP protocol.
RFC 822 Support Functions
Documentation on public RFC-822/MIME functions.
This is primarily of interest for implementors of new c-client
drivers and advanced application developers.
Operating System-Dependent Public Interface
Documentation on OS-dependent functions. With the exception of
fs_get(), fs_give(), and fs_resize(), which should be called
instead of malloc(), free(), and realloc(), these functions are
primarily of interest for implementors of new c-client drivers.
Main Program Callbacks
Documentation of functions which the main program must provide
as callbacks from c-client.
Driver Interface
Documentation of the driver dispatch vector and the functions
which a driver must supply.
This is primarily of interest for implementors of new c-client
drivers.
Driver Support Functions
Documentation of support functions which are called by drivers.
This is primarily of interest for implementors of new c-client
drivers.
History
The c-client API was originally written by Mark Crispin at Stanford
University as a set of routines to support IMAP and SMTP from a main
program which would handle the user interface. In its original form, it
was written as the low-level routines that were to be used as part of a
Macintosh client.
The first IMAP client, MM-D (for "MM on Xerox D machines" -- MM was a
popular DEC-20 mail program) was written in Interlisp for Xerox Lisp
machines. At that time, there was no name for the embryonic Mac client,
but since it was the first one to be written in C instead of Lisp, it was
given a development name of "C client". This name became "c-client"
because that is the name of the subdirectory on UNIX where the source files
were stored.
To exercise the routines, a minimal main program which uses c-client,
mtest, was written. mtest has subsequently been extended so that it runs
on every platform that c-client is ported.
The real Mac client, was eventually written by Frank Gilmurrary and
Bill Yeager at Stanford using the autumn 1988 version of c-client and named
"MacMS". In the winter of 1988-89, Mark Crispin, who had changed jobs to
the University of Washington, developed MS as an MM-like text-based program
for UNIX and MailManager as a GUI-based program for NeXT machines.
The realization sunk in that this API needed its own name. As early
as spring 1989, there were at least four programs (mtest, MS, MailManager,
and MacMS) that used it. The name c-client thus became permanent.
In its history, c-client has undergone two major redesigns, both by
Mark Crispin who is now on the staff at the University of Washington.
The first major redesign added the following:
1) ANSI C calling conventions throughout to assist in function
argument type checking.
2) Vectoring mail access calls through "driver" methods; thus
providing transparent access to multiple types of mail
stores with the same call.
3) MIME support.
The second major redesign was part of the IMAP4 project. Many
c-client functions were extended with additional arguments and options.
The driver interface was also made simpler, with more work done by
driver-independent code.
Overview
The most important file for the author of an application using the
c-client is mail.h. mail.h defines several important structures of
data which are passed between the main program and the c-client.
Although some functions (e.g. mail_fetchtext_body()) return the data
fetched, for certain other data items (e.g. flags) you need to get the
data as a structure reference. mail.h also defines a large number of
useful constants and structures.
When a function in mail.h exists to reference data, it MUST be
used instead of referencing the structures directly. This is because
in some cases the data is not actually fetched until a reference (via
the function call) is made. For example, although the MESSAGECACHE
element for a message can be obtained by indexing the proper cache
element in the stream, there is no guarantee that the item in fact
exists unless mail_fetchstructure_full() is called for that message.
Less costly functions. also exist to create and load a MESSAGECACHE
element.
The main program will probably also need to include smtp.h,
misc.h, and osdep.h, but this usage should be solely to receive
function prototypes. Any other definitions in those files should be
considered private to that module.
Two important predefined symbols are NIL and T. NIL is any sort
of "false"; T is any sort of "true". NIL is also used to null-specify
certain optional arguments.
* * * IMPORTANT * * *
Any multi-threaded application should test stream->lock prior to
calling any c-client stream functions. Any attempt to call a
mail_xxx() function while one is already in progress on the same
stream will cause the application to fail in unpredictable ways.
Note that this check is insufficient in a preemptive-scheduling
multi-tasking application due to the possibility of a timing race.
Such applications must be written so that only one process accesses
the stream, or to have a higher level lock.
Since MAIL operations will not finish until they are completed, a
single-tasking application does not have to worry about this problem,
except in the callback invoked from MAIL (e.g. mm_exists(), etc.) in which
case the stream is *always* locked.
c-client Structures
c-client has a large number of structures which are used for
multiple functions. The most important of these are described here.
The MAILSTREAM structure is used to reference open mailboxes.
Applications may reference the following:
char *mailbox; mailbox name
unsigned short use; stream use count, this is incremented
unsigned short sequence; stream sequence, this is incremented
each time a stream is reused (i.e.
mail_open() is called to open a
different mailbox on this stream)
unsigned int rdonly : 1; stream is open read-only
unsigned int anonymous : 1; stream is open with anonymous access
unsigned int halfopen : 1; stream is half-open; it can be
reopened or used for functions that
don't need a open mailbox such as
mail_create() but no message data
can be fetched
unsigned int perm_seen : 1; Seen flag can be set permanently
unsigned int perm_deleted : 1; Deleted flag can be set permanently
unsigned int perm_flagged : 1; Flagged flag can be set permanently
unsigned int perm_answered :1; Answered flag can be set permanently
unsigned int perm_draft : 1; Draft flag can be set permanently
unsigned int kwd_create : 1; new user flags can be created by
referencing then in mail_setflag() or
mail_clearflag(). Note: this can
change during a session (e.g. if
there is a limit on the number of
keywords), so check after creating a
new flag to see if any more can be
created before letting the user try
to do so
unsigned long perm_user_flags; corresponding user flags can be set
permanently. This is a bit mask
which matches the entries in
stream->user_flags[]
unsigned long gensym; generated unique value. Always
referenced with stream->gensys++
unsigned long nmsgs; number of messages in current mailbox
unsigned long recent; number of recent messages in current
mailbox
unsigned long uid_validity; UID validity value; this is used to
verify that recorded UIDs match the
UIDs that the stream has. If the
mailbox does not have matching UIDs
(e.g. the UIDs were lost or not
recorded) then the UID validity value
will be different
unsigned long uid_last; highest currently assigned UID in the
current mailbox; a new UID will be
assigned with ++stream->uid_last
char *user_flags[NUSERFLAGS]; pointers to user flag names in bit
order from stream->perm_user_flags or
elt->user_flags
The following MAILSTREAM values are only used internally:
DRIVER *dtb; dispatch table for this driver
void *local; pointer to driver local data
unsigned int lock : 1; stream lock flag (an operation is in
progress; used as a bug trap to
detect recursion back to c-client
from callback routines).
unsigned int debug : 1; debugging information should be logged
via mm_dlog().
unsigned int silent : 1; don't do main program callbacks on
this stream (used when a stream is
opened internally)
unsigned int scache : 1; short caching; don't cache information
in memory
The following MAILSTREAM values are only used by the cache
manager routine (see the documentation about mailcache_t above):
unsigned long cachesize; size of c-client message cache
union {
void **c; to get at the cache in general
MESSAGECACHE **s; message cache array
LONGCACHE **l; long cache array
} cache;
The following MAILSTREAM values are for the convenience of
drivers that use short caching and want to be able to garbage collect
any values that they returned:
unsigned long msgno; message number of `current' message
ENVELOPE *env; pointer to `current' message envelope
BODY *body; pointer to `current' message body
char *text; pointer to `current' text
The MESSAGECACHE structure (commonly called an "elt" as a
nickname for "cache ELemenT") contains information about messages.
Applications may use the following:
unsigned long msgno; message number. If the elt is locked
(by elt->lockcount++), then the elt
pointer can be stored (e.g. with the
data for a window which draws this
message) and elt->msgno will change
automatically whenever expunges are
done so the window will always view
the correct message. If elt->msgno
becomes 0, then the message has been
expunged, but the elt won't be freed
until the elt lock count is
decremented (by mail_free_elt()).
unsigned long uid; message unique ID
unsigned int hours: 5; internal date hours (0-23)
unsigned int minutes: 6; internal date minutes (0-59)
unsigned int seconds: 6; internal date seconds (0-59)
unsigned int zoccident : 1; non-zero if internal date time zone is
west of UTC
unsigned int zhours : 4; internal date time zone hours from UTC
(0-12)
unsigned int zminutes: 6; internal date time zone minutes (0-59)
unsigned int seen : 1; message Seen flag
unsigned int deleted : 1; message Deleted flag
unsigned int flagged : 1; message Flagged flag
unsigned int answered : 1; message Answered glag
unsigned int draft : 1; message Draft flag
unsigned int valid : 1; flags are valid in this elt; an elt
that was newly created but never
loaded with flags won't have this set.
unsigned int recent : 1; message recent flag
unsigned int searched : 1; message matches search criteria in
most recent mail_search_full() call
unsigned int spare : 1; reserved for application use
unsigned int spare2 : 1; reserved for application use
unsigned int spare3 : 1; reserved for application use
unsigned int lockcount : 8; non-zero if multiple references to
this elt. Refer to the msgno member
for more information.
unsigned int day : 5; internal date day of month (1-31)
unsigned int month : 4; internal date month of year (1-12)
unsigned int year : 7; internal date year since BASEYEAR
(currently 1970; was 1969 in older
versions so use BASEYEAR instead of
having the base year wired in)
unsigned long user_flags; message user flags; this is a bit mask
which matches the entries in
stream->user_flags[]
unsigned long rfc822_size; size of message in octets
The following MESSAGECACHE values are only used internally by
drivers:
unsigned int sequence : 1; message is in sequence from either
mail_sequence() or mail_uid_sequence()
unsigned long data1; first data item
unsigned long data2; second data item
unsigned long data3; third data item
unsigned long data4; fourth data item
The ADDRESS structure is a parsed form of a linked list of RFC 822
addresses. It contains the following information:
char *personal; personal name phrase
char *adl; at-domain-list (also called "source
route")
char *mailbox; mailbox name
char *host; domain name of mailbox's host
char *error; error in address from smtp_mail(); if
an error is returned from smtp_mail()
for one of the recipient addresses
the SMTP server's error text for that
recipient can be found here. If it
is null then there was no error (or
an error was found with a prior
recipient
ADDRESS *next; pointer to next address in list
The ENVELOPE structure is a parsed form of the RFC 822 header.
Its member names correspond to the RFC 822 field names. It contains
the following information:
char *remail; remail header if any
ADDRESS *return_path; error return address
char *date; message composition date string
ADDRESS *from; from address list
ADDRESS *sender; sender address list
ADDRESS *reply_to; reply address list
char *subject; message subject string
ADDRESS *to; primary recipient list
ADDRESS *cc; secondary recipient list
ADDRESS *bcc; blind secondary recipient list
char *in_reply_to; replied message ID
char *message_id; message ID
char *newsgroups; USENET newsgroups
char *followup_to; USENET reply newsgroups
char *references; USENET references
The BODY structure is a parsed form of a linked list of the MIME
structure of a message. It contains the following information.
unsigned short type; body primary type code. This is an
index into the body_types vector of
body type names. The following body
types are pre-defined:
TYPETEXT unformatted text
TYPEMULTIPART multiple part
TYPEMESSAGE encapsulated message
TYPEAPPLICATION application data
TYPEAUDIO audio
TYPEIMAGE static image (GIF, JPEG, etc.)
TYPEVIDEO video
TYPEOTHER unknown
Additional types up to TYPEMAX are
dynamically defined if they are
encountered by c-client.
unsigned short encoding; body transfer encoding. This is an
index into the body_encodings vector
of body encoding names. The
following body encodings are
pre-defined:
ENC7BIT 7 bit SMTP semantic data
ENC8BIT 8 bit SMTP semantic data
ENCBINARY 8 bit binary data
ENCBASE64 base-64 encoded data
ENCQUOTEDPRINTABLE human-readable 8-as-7 bit data
ENCOTHER unknown
Additional encodings up to ENCMAX are
dynamically defined if they are
encountered by c-client.
char *subtype; body subtype string
PARAMETER *parameter; parameter list
char *id; body content identifier
char *description; body content description
unsigned char *contents.text; when composing a message that is NOT
of TYPEMULTIPART, non-binary text of
the content is stored here. Note that
this happens even when the text is
of TYPEMESSAGE. Text of encoding
ENC8BIT may be converted to
ENCQUOTEDPRINTABLE when it is sent.
This should not be referenced for any
other reason; in particular, this is
NOT the way for an application to
access content data (use
mail_fetchbody_full() instead).
BINARY *contents.binary; when composing a message that is NOT
of TYPEMULTIPART, binary content (of
encoding ENCBINARY) is stored here.
It will be converted to ENCBASE64 when
it is sent.
This should not be referenced for any
other reason; in particular, this is
NOT the way for an application to
access content data (use
mail_fetchbody_full() instead).
PART *contents.part; for body parts of TYPEMULTIPART, this
contains the list of body parts in
this multipart
MESSAGE contents.msg; for body parts of TYPEMESSAGE with
subtype "RFC822", this contains the
encapsulated message
unsigned long size.lines; size in lines
unsigned long size.bytes; size in octets. This MUST be set when
composing a message if the encoding is
ENC8BIT or ENCBINARY.
char *md5; body content MD5 checksum
The following BODY information is used only by c-client
internally. The use of this data is driver-specific and it can not be
relied-upon by applications.
unsigned char *contents.text; drivers can store a pointer to the
body contents as text here.
unsigned long size.ibytes; internal size of the body content (prior
to newline conversion, etc.) in octets
The MESSAGE structure is a parsed form of a MESSAGE/RFC822 MIME
body part. It contains the following information:
ENVELOPE *env; encapsulated message RFC 822 header
BODY *body; encapsulated message MIME structure
The following MESSAGE information is used only by c-client
internally. The use of this data is driver-specific and it can not be
relied-upon by applications.
char *hdr; encapsulated message header
unsigned long hdrsize; message header size
char *text; message in RFC 822 form
unsigned long offset; offset of text from header
The PARAMETER structure is a parsed form of a linked list of
attribute/value pairs. It contains the following information:
char *attribute; attribute name
char *value; value
PARAMETER *next; next parameter in list
The PART structure is a parsed form of a linked list of MIME body
parts. It contains the following information:
BODY body; body information for this part
PART *next; next body part
The following PART information is used only by c-client
internally. The use of this data is driver-specific and it can not be
relied-upon by applications.
unsigned long offset; offset from body origin
The NETMBX structure is a parsed form of a network mailbox name:
char host[NETMAXHOST]; remote host name
char user[NETMAXUSER]; remote user name if specified
char mailbox[NETMAXMBX]; remote mailbox name
char service[NETMAXSRV]; remote service name (IMAP4, NNTP, etc.)
unsigned long port; TCP/IP port number if specified
unsigned int anoflag : 1; anonymous access requested
unsigned int dbgflag : 1; protocol debugging telemetry, via
mm_dlog(), requested
The STRINGLIST structure is a list of strings (which may have
embedded NULs) and their lengths:
char *text; string text
unsigned long size; string length
STRINGLIST *next; next string in list
String Structures
A string structure is analogous to a char*, and is used in some
functions as an input argument. It represents a string of data in a
way that does not necessarily require the entire string to be in
memory at once. This is essential for small machines with
highly-restricted memory limits (e.g. DOS).
String Structure Access
To use a string structure, the caller needs to know a string
driver and needs to know the driver-dependent data used by that string
structure. A simple string driver is mail_string, a string driver
that takes an in-memory char* string as the driver-dependent data.
The DOS port uses string drivers that take a struct holding a file
descriptor and a file offset. Often the user of a string driver is
the same module that defined it, so usually the programmer knows about
its conventions.
The following calls are used to access a string structure:
void INIT (STRING *s,STRINGDRIVER *d,void *data,unsigned long size);
s pointer to the string structure to be initialized
d pointer to the string driver
data pointer to driver-dependent data, from which the
driver can determine string data
size size of the string
This call initializes the string stucture.
unsigned long SIZE (STRING *s);
s pointer to the string structure
This call returns the number of characters remaining in the string
after the current string character pointer.
char CHR (STRING *s);
s pointer to the string structure
This call returns the character at the current string character
pointer.
char SNX (STRING *s);
s pointer to the string structure
This call returns the character at the current string character
pointer, and increments the string character pointer.
unsigned long GETPOS (STRING *s);
s pointer to the string structure
This returns the value of the current string character pointer.
void SETPOS (STRING *s,unsigned long i);
s pointer to the string structure
i new string pointer value
This method sets the string character pointer to the given value.
String Structure Internals
A string structure holds the following data:
void *data; used by the string driver as it likes
unsigned long data1; used by the string driver as it likes
unsigned long size; static, holds the total length of the string
from the INIT call
char *chunk; current chunk of in-memory data; this is used
for buffering to avoid unnecessary calls to
the string driver's next method.
unsigned long chunksize; size of an in-memory data chunk
unsigned long offset; position of first character of the chunk in
the overall string
char *curpos; current position; this is what CHR() will
access
unsigned long cursize; number of characters remaining in the current
string
STRINGDRIVER *dtb; the string driver for this string structure
A string structure is manipulated by a string driver, which has
the following access methods:
void (*init) (STRING *s,void *data,unsigned long size);
s pointer to the string structure to be initialized
data pointer to driver-dependent data, from which the
driver can determine string data
size size of the string
This method initializes the string stucture. It can use the data,
data1, and chunksize values as it likes. The remaining values must be
set up as follows:
size static, copied from the size argument
chunk pointer to a buffer loaded with initial data
chunksize size of the buffer
offset 0
curpos copied from chunk
cursize copied from chunksize
dtb STRINGDRIVER identity pointer
char (*next) (STRING *s);
s pointer to the string structure
This method returns the character at the current string character
pointer, and increments the string character pointer. This method
is likely to call the setpos method if the desired character is not in
the current chunk.
void (*setpos) (STRING *s,unsigned long i);
s pointer to the string structure
i new string pointer value
This method sets the string character pointer to the given value. If
the pointer is not in the current chunk, then a new chunk is loaded
and the associated values (chunk, offset, curpos, cursize) are
adjusted accordingly.
c-client Support Functions
void mail_string_init (STRING *s,void *data,unsigned long size);
char mail_string_next (STRING *s);
void mail_string_setpos (STRING *s,unsigned long i);
These three functions are the init, next, and setpos string
structure access methods for the build-in mail_string string driver.
mail_string is a basic string driver for a char* string. See the
documentation below on "String Structures" for more information.
void mail_link (DRIVER *driver);
driver pointer to the driver to be added
This function adds the specified driver to the list of mailbox
drivers. Initially there are no drivers lunk, so all programs which
intend to use c-client need to have at least one call to this function.
A function which uses IMAP4 would have a statement such as:
mail_link (&imapdriver); /* link in IMAP driver */
early in the program's initialization. Normally, this is done by the
statement
#include "linkage.c"
which will include the "system standard driver linkage" defined when
c-client was built. By using linkage.c instead of explicit mail_link()
calls, you are guaranteed that you will have a consistant linkage among
all software built on this system.
void auth_link (AUTHENTICATOR *auth);
auth pointer to the authenticator to be added
This function adds the specified authenticator to the list of
authenticators. Initially there are no authenticators lunk. Normally,
this is done by linkage.c so you don't need to call this routine
explicitly.
void *mail_parameters (MAILSTREAM *stream,long function,void *value);
stream stream to poll or NIL
function function code
value new value for function codes that change a parameter
This function fetches or changes the settings of various c-client
operational parameters depending upon the function. If the stream is
specified, only the action for the underlying driver for that stream is
taken; however, the scope of the operational parameters is global so
there is generally no reason for the stream argument ever to be
non-NIL.
The function codes ENABLE_DRIVER and DISABLE_DRIVER take a driver
pointer as a value. These functions enable and disable mailbox
processing by that driver. By default, all drivers are enabled.
The remaining function codes are in a pair named GET_xxx to
fetch an operational parameter and SET_xxx to set the parameter:
GET_DRIVERS / SET_DRIVERS
The list of currently lunk drivers.
GET_GETS / SET_GETS
If non-NIL, points to a function for reading message text.
Defaults to NIL.
This function is called with three arguments; a function
pointer to a "reading function", a stream for the reading
function, and a size in octets. The reading function is
in turn called with the stream, a size in octets, and a
pointer to a readin buffer.
This function returns with a char* string, which will be
returned by the mail_fetchheader(), mail_fetchtext(), or
mail_fetchbody() function which triggered the message text
reading.
The purpose is to permit reading of large strings, without
requiring an in-memory buffer for the entire string. The idea
is that this function can store the data in some form other
than a char* (e.g. a temporary file) and the main program will
recognize that it should get the text from there instead of
from the results from mail_fetch....().
This is only supported on DOS and Win16; on other platforms it
is inconsistent whether or not it works.
GET_CACHE / SET_CACHE
Points to the c-client cache manager function. Defaults to
mm_cache().
GET_SMTPVERBOSE / SET_SMTPVERBOSE
If non-NIL, points to a function that accepts a char* string.
This function is called any time the SMTP routines receive a
response code less than 100. The argument is the text of the
response code
GET_RFC822OUTPUT / SET_RFC822OUTPUT
If non-NIL, points to an alternate rfc822_output() function.
rfc822_output() will call this function and return instead of
doing its normal action. See the description of
rfc822_output() for more information.
GET_USERNAME / SET_USERNAME
The logged-in user name.
GET_HOMEDIR / SET_HOMEDIR
The home directory path name.
GET_LOCALHOST / SET_LOCALHOST
The local host name.
GET_SYSINBOX / SET_SYSINBOX
The "system INBOX" (where mail is delivered) path name.
GET_OPENTIMEOUT / SET_OPENTIMEOUT
TCP/IP open timeout in seconds. Defaults to 0 (system
default timeout, usually 75 seconds on Unix).
GET_READTIMEOUT / SET_READTIMEOUT
TCP/IP read timeout in seconds. Defaults to 0 (no timeout).
GET_WRITETIMEOUT / SET_WRITETIMEOUT
TCP/IP write timeout in seconds. Defaults to 0 (no timeout).
GET_CLOSETIMEOUT / SET_CLOSETIMEOUT
TCP/IP close timeout in seconds. Defaults to 0 (no timeout).
GET_TIMEOUT / SET_TIMEOUT
If non-NIL, points to the function called when a TCP/IP
timeout occurs. This function is called with the number of
seconds since the start of the TCP operation. If it returns
non-zero, the TCP/IP operation is continued; if it returns
non-zero, the TCP/IP connection is aborted.
GET_RSHTIMEOUT / SET_RSHTIMEOUT
rsh connection timeout in seconds. Defaults to 15 seconds.
GET_MAXLOGINTRIALS / SET_MAXLOGINTRIALS
The maximum number of login attempts permitted in an IMAP or
POP connection. Defaults to 3.
GET_LOOKAHEAD / SET_LOOKAHEAD
The number of subsequent envelopes prefetched in IMAP when an
envelope is fetched. Defaults to 20.
GET_IMAPPORT / SET_IMAPPORT
The IMAP port number. Defaults to 143.
GET_PREFETCH / SET_PREFETCH
The number of envelopes prefetched in IMAP from the results
of a SEARCH. Defaults to 20.
GET_CLOSEONERROR / SET_CLOSEONERROR
If non-NIL, close an opening IMAP connection if the SELECT
command fails instead of returning a half-open stream.
Defaults to NIL.
GET_POP3PORT / SET_POP3PORT
The POP3 port number. Defaults to 110.
GET_UIDLOOKAHEAD / SET_UIDLOOKAHEAD
The number of UIDs premapped when a message number is
translated to a UID. Defaults to 1000.
GET_MBXPROTECTION / SET_MBXPROTECTION
Default file protection for newly created mailboxes.
Defaults to 0600.
GET_DIRPROTECTION / SET_DIRPROTECTION
Default file protection for newly created directories.
Defaults to 0700.
GET_LOCKPROTECTION / SET_LOCKPROTECTION
Default file protection for locks. Defaults to 0666.
WARNING: don't blithely change this. If other processes
can't get access to a lock then they will have trouble in
locking properly.
GET_FROMWIDGET / SET_FROMWIDGET
If non-NIL, APPEND in the Unix mbox format will insert a
">" character in front of all lines which begin with the
string "From ". If NIL, it will only do so if the entire
line looks like a message delimiter (that is, the date is
also in correct format). Defaults to T.
GET_NEWSACTIVE / SET_NEWSACTIVE
Netnews active file path name.
GET_NEWSSPOOL / SET_NEWSSPOOL
Netnews spool directory path name.
GET_NEWSRC / SET_NEWSRC
Netnews newsgroup reading status file (.newsrc) path name.
GET_EXTENSION / SET_EXTENSION
If non-NIL, points to a string holding the extension for all
mailbox files. This is only supported on DOS and Win16.
GET_DISABLEFCNTLLOCK / SET_DISABLEFCNTLLOCK
If non-NIL, disables fcntl() locking on SVR4. This is done
if fcntl() tends to hang for no good reason. Now that the
fcntl() code checks for NFS files and no-ops the locking,
this problem usually doesn't happen much any more. Defaults
to NIL.
GET_LOCKEACCESERROR / SET_LOCKEACCESERROR
If non-NIL, give a warning if an attempt to create a .lock
file gets an EACCES ("Permission denied") error. This usually
means that somebody protected the system inbox directory (e.g.
/var/mail) instead of making it public-write with the sticky
bit. Defaults to non-NIL, since this is usually bad news.
GET_LISTMAXLEVEL / SET_LISTMAXLEVEL
The maximum depth of recusion that LIST will go on a *
wildcard. Defaults to 20.
GET_ANONYMOUSHOME / SET_ANONYMOUSHOME
The anonymous use home directory name.
typedef long (*readfn_t) (void *stream,unsigned long size,char *buffer);
stream a designator suitable
size a number of octets to read
buffer a buffer of at least size octets for readin
This function reads the given number of octets into the buffer,
using the given stream. What sort of object the stream is depends upon
the function and its caller, so you must make sure that the readfn is
suitable for the caller's purpose. Common uses include support of the
mailgets function (see below) and of reading from local files on systems
with limited address space.
typedef char *(*mailgets_t) (readfn_t f,void *stream,unsigned long size);
f the readfn to use
stream stream argument for the readfn
size total number of octets to read
This is the argument to the SET_GETS mail_parameter() call. This
function must read size octets from the stream, using the readfn f. It
may call f multiple times to accomplish this; this will read the data in
a serial fashion. So, for example, if size is a megabyte and there is
only 4K of available buffer space, it can call f 256 times to satisfy
the request. There is no way to back up in the reading, so any
processing or saving of the data must be done when it is read.
The function mm_gets() in mail.c is a sample mailgets function; it
reads the first MAXMESSAGESIZE of data into memory and discards the
rest.
typedef void *(*mailcache_t) (MAILSTREAM *stream,unsigned long msgno,long op);
stream stream to cache manage
msgno message to cache manage in the stream
op cache management operation
This function manages the c-client cache. Normally, a program will
use the default c-client cache manager routine mm_cache(). However, a
main program may want to supply its own cache manager, e.g. it may want
to store the data on a disk file instead of in memory on DOS and Win16
where memory is tight.
If you write your own cache manager, you need to examine the
default mm_cache() manager closely, as well as paying close attention to
what goes into an elt (a MESSAGECACHE element). It is highly likely
that if you roll elts out to disk, you will want to set stream->scache
and *NOT* use long elts (because long elts have ENVELOPE and BODY
pointers that you would have to know how to write to disk and read back).
The cache management functions are one of the following:
CH_INIT Initialize the entire cache for the stream. This is
called only when creating a new stream or when freeing
it. The msgno argument is ignored.
CH_SIZE Make sure that the cache is at least large enough to
support msgno. This is a request to grow the cache if
necessary, not shrink it.
CH_MAKELELT Return a long elt for msgno, creating it if necessary.
This is the underlying support function for mail_lelt().
CH_LELT Return the long elt for msgno, or NIL if it does not
already exist.
CH_MAKEELT Return an elt for msgno, creating it if necessary.
This is the underlying support function for mail_elt().
CH_ELT Return the elt for msgno, or NIL if it does not already
exist.
CH_FREE Free the [l]elt for msgno.
CH_EXPUNGE Free the [l]elt for msgno, and reclaim its position.
All subsequent elts are renumbered with their elt->msgno
decremented by 1. [Hence msgno+1 becomes msgno, etc.]
This supports message expunging from the cache.
typedef long (*tcptimeout_t) (long time);
time total time spent since TCP operation started
This function is called when a TCP operation times out. It is set
by the SET_TIMEOUT mail_parameter(). The function can return non-zero
to continue the TCP operation (e.g. after outputting a "do you still
want to wait" prompt) or zero if it wants the TCP operation to abort and
close. If the TCP operation aborts, it will likely cause the upper
level IMAP, SMTP, etc. stream to abort and close as well.
DRIVER *mail_valid (MAILSTREAM *stream,char *mailbox,char *purpose);
stream if non-NIL, stream to use for validation
mailbox mailbox name to validate
purpose filled in as xxx in "Can't xxx" in error messages
This function validates the given mailbox name. It successful, it
returns the driver that can open that name if successful, otherwise it
returns NIL. If stream is non-NIL, the mailbox name must be valid for
the type of mailbox associated with that stream (e.g. an NNTP name can
not be used with an IMAP stream). If purpose is non-NIL, an error
message is passed via mm_log() when an error occurs.
DRIVER *mail_valid_net (char *name,DRIVER *drv,char *host,char *mailbox);
name mailbox name to validate
drv driver name to validate against
host buffer to return host name if non-NIL
mailbox buffer to return remote mailbox name if non-NIL
This function is an alternative to mail_valid_net_parse(). It
validates the given mailbox name as a network name and makes sure that
its service name is the same as the driver in drv. If successful, it
returns drv, and copies the host and mailbox strings as needed.
Otherwise it returns NIL.
long mail_valid_net_parse (char *name,NETMBX *mb);
name mailbox name to parse
mb pointer to NETMBX structure to return
This function parses a network mailbox name. If the name is a
network mailbox name, it returns non-NIL, with the NETMBX structure
loaded with the results form the parse.
Mailbox Access Functions
void mail_list (MAILSTREAM *stream,char *ref,char *pat);
void mail_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);
stream if non-NIL, stream to use
ref mailbox reference string
pat mailbox pattern string
contents contents to search
This function returns a list of mailboxes via the mm_list()
callback. The reference is applied to the pattern in an implementation
dependent fashion, and the resulting string is used to search for
matching mailbox names. "*" is a wildcard which matches zero or more
characters; "%" is a variant which does not descend a hierarchy level.
Read the IMAP specification for more information.
mail_scan() is a variant which takes a string to search for in the
text of the mailbox. The string is a free-text string, without regard
for message boundaries, and thus the choice of strings must be made
with care.
void mail_lsub (MAILSTREAM *stream,char *ref,char *pat);
stream if non-NIL, stream to use
ref mailbox reference string
pat mailbox pattern string
This function returns a list of subscribed mailboxes via the
mm_lsub() callback. The reference is applied to the pattern in an
implementation dependent fashion, and the resulting string is used to
search for matching mailbox names in the subscription list. "*" is a
wildcard which matches zero or more characters; "%" is a variant which
does not descend a hierarchy level. Read the IMAP specification for
more information.
long mail_subscribe (MAILSTREAM *stream,char *mailbox);
stream if non-NIL, stream to use
mailbox mailbox name
This function adds the given name to the subscription list. It
returns T if successful, NIL if unsuccessful. If unsuccessful, an
error message is returned via the mm_log() callback.
long mail_unsubscribe (MAILSTREAM *stream,char *mailbox);
stream if non-NIL, stream to use
mailbox mailbox name
This function removes the given name from the subscription list.
It returns T if successful, NIL if unsuccessful. If unsuccessful, an
error message is returned via the mm_log() callback.
long mail_create (MAILSTREAM *stream,char *mailbox);
stream if non-NIL, stream to use
mailbox mailbox name
This function creates a mailbox with the given name. It returns T
if successful, NIL if unsuccessful. If unsuccessful, an error message
is returned via the mm_log() callback.
It is an error to create INBOX or a mailbox name which already
exists.
long mail_delete (MAILSTREAM *stream,char *mailbox);
stream if non-NIL, stream to use
mailbox mailbox name
This function deletes the named mailbox. It returns T if
successful, NIL if unsuccessful. If unsuccessful, an error message is
returned via the mm_log() callback.
It is an error to delete INBOX or a mailbox name which does not
already exist.
long mail_rename (MAILSTREAM *stream,char *old,char *newname);
stream if non-NIL, stream to use
old existing mailbox name
newname new (not yet existing) mailbox name
This function renames the old mailbox to the new mailbox name.
It returns T if successful, NIL if unsuccessful. If unsuccessful, an
error message is returned via the mm_log() callback.
It is an error to reanme a mailbox that does not exist, or rename
a mailbox to a name that already exists. It is permitted to rename
INBOX; a new empty INBOX is created in its place.
long mail_status (MAILSTREAM *stream,char *mbx,long flags);
stream if non-NIL, stream to use
mbx mailbox name
flags option flags
This function returns the status of the given mailbox name via the
mm_status() callback. It returns T if successful, NIL if unsuccessful.
If unsuccessful, an error message is returned via the mm_log()
callback.
The options are a bit mask with one or more of the following,
indicating the data which should be returned.
SA_MESSAGES number of messages in the mailbox
SA_RECENT number of recent messages in the mailbox
SA_UNSEEN number of unseen messages in the mailbox
SA_UIDNEXT next UID value to be assigned
SA_UIDVALIDITY UID validity value
Note that, depending upon implementation, some of these values may
be more costly to get than others. For example, calculating the
number of unseen messages may require opening the mailbox and scanning
all of the message flags. A mail_status() call should thus be used
with option flags specifying only the data that is actually needed.
MAILSTREAM *mail_open (MAILSTREAM *oldstream,char *name,long options);
oldstream if non-NIL, stream to recycle
name mailbox name to open
options option flags.
This function opens the mailbox and if successful returns a stream
suitable for use by the other MAIL functions.
If oldstream is non-NIL, an attempt is made to reuse oldstream as
the stream for this mailbox; this is useful when you want to open
another mailbox to the same IMAP or NNTP server without having to open
a new connection. Doing this will close the previously open mailbox.
The options are a bit mask with one or more of the following:
OP_DEBUG Log IMAP protocol telemetry through mm_debug()
OP_READONLY Open mailbox read-only.
OP_ANONYMOUS Don't use or update a .newsrc file for news.
OP_SHORTCACHE Don't cache envelopes or body structures
OP_SILENT Don't pass mailbox events (internal use only)
OP_PROTOTYPE Return the "prototype stream" for the driver
associated with this mailbox instead of
opening the stream
OP_HALFOPEN For IMAP and NNTP names, open a connection
to the server but don't open a mailbox.
OP_EXPUNGE Silently expunge the oldstream before recycling
NIL is returned if this function fails for any reason.
MAILSTREAM *mail_close (MAILSTREAM *stream);
MAILSTREAM *mail_close_full (MAILSTREAM *stream,long options);
stream stream to close
options option flags
This function closes the MAIL stream and frees all resources
associated with it that it may have created (subject to any handles
existing).
The options for mail_close_full() are a bit mask with one or more
of the following:
CL_EXPUNGE Silently expunge before closing
This function always returns NIL, so it can be used as:
stream = mail_close (stream);
Handle Functions
Handles are used when an entity that wishes to access the stream
may survive the stream without knowing that it outlived it. For
example, an object reading a message may have a handle to a stream,
but the message selection object that spawned it (and which owns the
stream) may have gone away. A stream can be closed or recycled while
handles are pointing at it, but it is not completely freed until all
handles are gone. A stream may have an arbitrary number of handles.
MAILHANDLE *mail_makehandle (MAILSTREAM *stream);
stream stream to make handle to
This function creates and returns a handle to the stream.
void mail_free_handle (MAILHANDLE **handle);
handle pointer to handle to release
This function frees the handle and notifies the stream that it has
one fewer handle. If this is the last handle on the stream and the
stream has been closed, then the stream is freed.
MAILSTREAM *mail_stream (MAILHANDLE *handle);
handle handle to look up
This function returns the stream associated with the handle if and
only if the stream still represents the same MAIL connection associated
with the handle. Otherwise, NIL is returned (meaning that there is no
active stream associated with this handle).
Message Data Fetching Functions
[Note!! There is an important difference between a "sequence" and a
"msgno". A sequence is a string representing one or more messages in
IMAP4-style sequence format ("n", "n:m", or combination of these
delimited by commas), whereas a msgno is an int representing a single
message.]
void mail_fetchfast (MAILSTREAM *stream,char *sequence);
void mail_fetchfast_full (MAILSTREAM *stream,char *sequence,long flags);
stream stream to fetch on
sequence IMAP-format set of message sequence numbers
flags option flags
This function causes a cache load of all the "fast" information
(internal date, RFC 822 size, and flags) for the given sequence. Since
all this information is also fetched by mail_fetchstructure(), this
function is generally not used unless the OP_SHORTCACHE option in the
mail_open() call is used.
The options for mail_fetchfast_full() are a bit mask with one or
more of the following:
FT_UID The sequence argument contains UIDs instead of
sequence numbers
void mail_fetchflags (MAILSTREAM *stream,char *sequence);
void mail_fetchflags_full (MAILSTREAM *stream,char *sequence,long flags);
This function causes a fetch of the flags for the given sequence.
This main reason for using this function is to update the flags in the
local cache in case some other process changed the flags (multiple
simultaneous write access is allowed to the flags) as part of a "check
entire mailbox" (as opposed to "check for new messages") operation.
The options for mail_fetchflags_full() are a bit mask with one or more
of the following:
FT_UID The sequence argument contains UIDs instead of
sequence numbers
ENVELOPE *mail_fetchenvelope (MAILSTREAM *stream,unsigned long msgno);
ENVELOPE *mail_fetchstructure (MAILSTREAM *stream,unsigned long msgno,
BODY **body);
ENVELOPE *mail_fetchstructure_full (MAILSTREAM *stream,unsigned long msgno,
BODY **body,long flags);
stream stream to fetch on
msgno message sequence number
body pointer to where to return BODY structure if non-NIL
flags option flags
This function causes a fetch of all the structured information
(envelope, internal date, RFC 822 size, flags, and body structure) for
the given msgno and, in the case of IMAP, up to MAPLOOKAHEAD (a
parameter in IMAP2.H) subsequent messages which are not yet in the
cache. No fetch is done if the envelope for the given msgno is already
in the cache. The ENVELOPE and the BODY for this msgno is returned.
It is possible for the BODY to be NIL, in which case no information is
available about the structure of the message body.
The options for mail_fetchstructure_full() are a bit mask with one
or more of the following:
FT_UID The msgno argument is a UID
This is the primary function for fetching non-text information
about messages, and should be called before any attempt to reference
cache information about this message via mail_elt().
char *mail_fetchheader (MAILSTREAM *stream,unsigned long msgno);
char *mail_fetchheader_full (MAILSTREAM *stream,unsigned long msgno,
STRINGLIST *lines,unsigned long *len,long flags);
stream stream to fetch on
msgno message sequence number
lines list of header lines to fetch
len returned length in octets
flags option flags
This function causes a fetch of the complete, unfiltered RFC 822
format header of the specified message as a text string and returns
that text string.
If the lines argument is non-NIL, it contains a list of header
field names to use in subsetting the header text. Only those lines
which have that header field name are returned, unless FT_NOT is set in
which case only those lines which do not have that header field name
are returned.
If the len argument is non-NIL, it holds a pointer in which the
length of the string in octets is returned. This is useful in cases
where there may be an embedded null in the string.
This function always returns a valid string pointer; if no header
exists or if it can not be fetched (e.g. by a deceased IMAP stream) an
empty string is returned.
The options for mail_fetchheader_full() are a bit mask with one or
more of the following:
FT_UID The msgno argument is a UID
FT_NOT The returned header lines are those that are
not in the lines argument
FT_INTERNAL The return string is in "internal" format,
without any attempt to canonicalize to CRLF
newlines
FT_PREFETCHTEXT The RFC822.TEXT should be pre-fetched at the
same time. This avoids an extra RTT on an
IMAP connection if a full message text is
desired (e.g. in a "save to local file"
operation)
char *mail_fetchtext (MAILSTREAM *stream,unsigned long msgno);
char *mail_fetchtext_full (MAILSTREAM *stream,unsigned long msgno,
unsigned long *len,long flags);
stream stream to fetch on
msgno message sequence number
len returned length in octets
flags option flags
This function causes a fetch of the non-header text of the
specified message as a text string and returns that text string. No
attempt is made to segregate individual body parts.
If the len argument is non-NIL, it holds a pointer in which the
length of the string in octets is returned. This is useful in cases
where there may be an embedded null in the string.
This function always returns a valid string pointer; if no header
exists or if it can not be fetched (e.g. by a deceased IMAP stream) an
empty string is returned.
The options for mail_fetchtext_full() are a bit mask with one or
more of the following:
FT_UID The msgno argument is a UID
FT_PEEK Do not set the \Seen flag if it not already set
FT_INTERNAL The return string is in "internal" format,
without any attempt to canonicalize to CRLF
newlines
char *mail_fetchbody (MAILSTREAM *stream,unsigned long msgno,char *sec,
unsigned long *len);
char *mail_fetchbody_full (MAILSTREAM *stream,unsigned long msgno,char *sec,
unsigned long *len,long flags);
stream stream to fetch on
msgno message sequence number
sec section specifier
len returned length in octets
flags option flags
This function causes a fetch of the particular section of the
body of the specified message as a text string and returns that text
string. The section specification is a string of integers delimited by
period which index into a body part list as per the IMAP4
specification. Body parts are not decoded by this function; see
rfc822_base64() and rfc822_quotedprintable().
If the len argument is non-NIL, it holds a pointer in which the
length of the string in octets is returned. This is useful in cases
where there may be an embedded null in the string.
This function may return NIL on error.
The options for mail_fetchbody_full() are a bit mask with one or
more of the following:
FT_UID The msgno argument is a UID
FT_PEEK Do not set the \Seen flag if it not already set
FT_INTERNAL The return string is in "internal" format,
without any attempt to canonicalize to CRLF
newlines
unsigned long mail_uid (MAILSTREAM *stream,unsigned long msgno);
stream stream to fetch on
msgno message sequence number
This function returns the UID for the given message sequence
number.
void mail_fetchfrom (char *s,MAILSTREAM *stream,unsigned long msgno,
long length);
s destination string
stream stream to fetch on
msgno message sequence number
length maximum field length
This function writes a "from" string of the specified length for
the specified message, suitable for display to the user in a menu line,
into the string pointed to by s.
If the personal name of the first address in the envelope's from
item is non-NIL, it is used; otherwise a string is created by appending
the mailbox of the first address, an "@", and the host of the first
address. The string is trimmed or padded with trailing spaces as
necessary to make its length match the length argument.
void mail_fetchsubject (char *s,MAILSTREAM *stream,unsigned long msgno,
long length);
s destination string
stream stream to fetch on
msgno message sequence number
length maximum field length
This function returns a "subject" string of the specified length
for the specified message, suitable for display to the user in a menu
line.
The envelope's subject item is copied and trimmed as necessary
to make its length be no more what the caller requested. Unlike
mail_fetchfrom(), this function can return a string of shorter length
than what the caller requested.
LONGCACHE *mail_lelt (MAILSTREAM *stream,unsigned long msgno);
MESSAGECACHE *mail_elt (MAILSTREAM *stream,unsigned long msgno);
stream stream to access
msgno message sequence number
This function returns the cache entry for the specified message.
Although it will create a cache entry if it does not already exist,
that functionality is for internal use only. This function should
never be called without having first called mail_fetchfast() or
mail_fetchstructure() on the message first.
A cache entry holds the internal date/time, flags, and RFC 822
size of a message. It holds other data as well, but that is for
internal use only.
mail_lelt() is a variant that returns a `long' cache entry, which
consists of an cache entry (as a structure, not a pointer), an envelope
pointer, and a body pointer. This is used in conjunction with the elt
lock count functionality, to allow an application to associate the
cached envelope and body of a message with an open window even if the
message is subsequently expunged or if the stream is closed.
Unless your application wants to look at cached envelopes and
bodies even after the message is expunged or the stream is closed, it
should not use mail_lelt(). Instead, it should use a returned elt from
mail_elt() and use the elt->msgsno as the argument to
mail_fetchstructure().
BEWARE: the behavior of mail_lelt() is undefined if the
stream is open with OP_SHORTCACHE. mail_lelt() is extremely
special purpose, and should only be used in sophisticated
special purpose applications after discussing its use with
the c-client author. If you think you need this function,
you are probably mistaken. In almost all cases, you should
use mail_elt() and mail_fetchstructure() instead.
Message Status Manipulation Functions
void mail_setflag (MAILSTREAM *stream,char *sequence,char *flag);
void mail_setflag_full (MAILSTREAM *stream,char *sequence,char *flag,
long flags);
stream stream to use
sequence IMAP-format set of message sequence numbers
flag IMAP-format flag string
flags option flags
This function causes a store to add the specified flag to the flags
set for the messages in the specified sequence. If there is any
problem in setting flags, a message will be passed to the application
via the mm_log() facility.
The options for mail_setflag_full() are a bit mask with one or
more of the following:
ST_UID The sequence argument contains UIDs instead of
sequence numbers
ST_SILENT Do not update the local cache with the new
value of the flags. This is useful to save
network bandwidth, at the cost of invalidating
the cache.
void mail_clearflag (MAILSTREAM *stream,char *sequence,char *flag);
void mail_clearflag_full (MAILSTREAM *stream,char *sequence,char *flag,
long flags);
stream stream to use
sequence IMAP-format set of message sequence numbers
flag IMAP-format flag string
flags option flags
This function causes a store to delete the specified flag from the
flags set for the messages in the specified sequence. If there is any
problem in clearing flags, a message will be passed to the application
via the mm_log() facility.
The options for mail_setflag_full() are a bit mask with one or
more of the following:
ST_UID The sequence argument contains UIDs instead of
sequence numbers
ST_SILENT Do not update the local cache with the new
value of the flags. This is useful to save
network bandwidth, at the cost of invalidating
the cache.
Mailbox Searching
void mail_search (MAILSTREAM *stream,char *criteria);
void mail_search_full (MAILSTREAM *stream,char *charset,SEARCHPGM *pgm,
long flags);
stream stream to search
charset MIME character set to use when searching strings
pgm search program
flags option flags
This function causes a mailbox search, using the given MIME
charset (NIL means the default, US-ASCII) and the given search program.
A search program is a structure that holds the following data:
SEARCHSET *msgno; a set of message sequence numbers
SEARCHSET *uid; a set of unique identifiers
SEARCHOR *or; OR result of two search programs
SEARCHPGMLIST *not; AND result of list of NOT'ed search programs
SEARCHHEADER *header; message headers
STRINGLIST *bcc; string(s) appear in bcc list
STRINGLIST *body; string(s) appear in message body text
STRINGLIST *cc; string(s) appear in cc list
STRINGLIST *from; string(s) appear in from
STRINGLIST *keyword; user flag string(s) set
STRINGLIST *unkeyword; user flag strings() not set
STRINGLIST *subject; string(s) appear in subject
STRINGLIST *text; string(s) appear in message header or body
STRINGLIST *to; string(s) appear in to list
unsigned long larger; larger than this many octets
unsigned long smaller; smaller than this many octes
The following dates are in form:
((year - BASEYEAR) << 9) + (month << 5) + day
unsigned short sentbefore;
sent before this date
unsigned short senton; sent on this date
unsigned short sentsince;
sent since this date
unsigned short before; received before this date
unsigned short on; received on this date
unsigned short since; received since this date
unsigned int answered : 1;
message answered
unsigned int unanswered : 1;
message not answered
unsigned int deleted : 1;
message deleted
unsigned int undeleted : 1;
message not deleted
unsigned int draft : 1; message is a draft
unsigned int undraft : 1;
message is not a draft
unsigned int flagged : 1;
message flagged as urgent
unsigned int unflagged : 1;
message not flagged as urgent
unsigned int recent : 1;
message recent since last parse of mailbox
unsigned int old : 1; message not recent since last parse of mailbox
unsigned int seen : 1; message read
unsigned int unseen : 1;
message not read
The following auxillary structures are used by search programs:
SEARCHHEADER: header line searching
char *line; header line field name
char *text; text header line
SEARCHHEADER *next; next SEARCHHEADER in list (AND'ed)
SEARCHSET: message number set
unsigned long first; first number in set
unsigned long last; if non-zero, last number in set
SEARCHSET *next; next SEARCHSET in list (AND'ed)
SEARCHOR: two search programs, OR'ed together
SEARCHPGM *first; first program
SEARCHPGM *second; second program
SEARCHOR *next; next SEARCHOR in list
SEARCHPGMLIST: list of search programs
SEARCHPGM *pgm; search program (AND'd with others in list)
SEARCHPGMLIST *next; next SEARCHPGM in list
mail_search(), the older interface, accepts a search criteria
argument as a character string in IMAP2 (RFC-1176) format. Do not try
to use any IMAP4 search criteria with this interface.
The application's mm_searched() function is called for each
message that matches the search criteria. In addition, after the
search is completed, the "fast" information (see mail_fetchfast_full()
and envelopes of the searched messages are fetched (this is called
pre-fetching).
If there is any problem in searching, a message will be passed to
the application via the mm_log() facility.
The flags for mail_search_full() are a bit mask with one or more
of the following:
SE_UID Return UIDs instead of sequence numbers
SE_FREE Return the search program to free storage after
finishing
SE_NOPREFETCH Don't prefetch searched messages.
unsigned long *mail_sort (MAILSTREAM *stream,char *charset,SEARCHPGM *spg,
SORTPGM *pgm,long flags);
stream stream to sort
charset MIME character set to use when sorting strings
spg search program
pgm sort program
flags option flags
This function is a variant of mail_search_full(). It accepts an
additional argument, a sort program, which specifies one or more sort
rules to be applied to the result. If the searching and sorting are
successful, it returns a 0-terminated vector of message sequence
numbers (or UIDs if SE_UID is set). This vector is created out of
free storage, and must be freed with fs_give() when finished with it.
A sort program is a structure that holds the following data:
unsigned int reverse : 1;
reverse sorting of this key
short function; sort rule, one of the following:
SORTDATE message Date
SORTARRIVAL arrival date
SORTFROM mailbox in first From address
SORTSUBJECT message Subject
SORTTO mailbox in first To address
SORTCC mailbox in first cc address
SORTSIZE size of message in octets
SORTPGM *next; next sort program to be applied if two or more
messages collate identically with this rule
The flags for mail_search_full() are a bit mask with one or more
of the following:
SE_UID Return UIDs instead of sequence numbers
SE_FREE Return the search program to free storage after
finishing
SE_NOPREFETCH Don't prefetch searched messages.
SO_FREE Return the sort program to free storage after
finishing
Miscellaneous Mailbox and Message Functions
long mail_ping (MAILSTREAM *stream);
stream string to ping
The function pings the stream to see if it is still active. It may
discover new mail; this is the preferred method for a periodic "new mail
check" as well as a "keep alive" for servers which have an inactivity
timeout. It returns T if the stream is still alive, NIL otherwise.
If new mail is found, the application's mm_exists() function is
called with the newly-determined number of messages in the mailbox.
void mail_check (MAILSTREAM *stream);
stream stream to checkpoint
This function causes a mailstore-defined checkpoint of the
mailbox. This may include such things as a writeback to disk, a check
for flag changes in a shared mailbox, etc. It is not a "check for new
mail"; mail_ping() performs this function (as potentially does any other
function). The status of the check is passed to the application via the
mm_log() facility.
void mail_expunge (MAILSTREAM *stream);
stream string to expunge
This function causes an expunge (permanent removal of messages
which are marked as deleted) of the mailbox. The application's
mm_expunged() function is called for each message that has been
expunged. The application's mm_exists() function is called at the start
and end of the expunge to ensure synchronization. The status of the
expunge is passed to the application via the mm_log() facility.
Note that the decrementing of msgno's for subsequent messages
happens immediately; for example, if three consequtive messages starting
at msgno 5 are expunged, mm_expunged() will be called with a msgno of 5
three times.
long mail_copy (MAILSTREAM *stream,char *sequence,char *mailbox);
long mail_move (MAILSTREAM *stream,char *sequence,char *mailbox);
long mail_copy_full (MAILSTREAM *stream,char *sequence,char *mailbox,
long options);
stream stream to copy
sequence IMAP-format set of message numbers
mailbox destination mailbox name
options option flags
This function causes the messages in the specified sequence to be
copied to the specified mailbox. T is returned if the copy is
successful. mail_move() is equivalent to setting CP_MOVE in the options.
If there is any problem in copying, a message will be passed to
the application via the mm_log() facility and the function returns NIL.
No copying is actually done in this case.
Note that the mailbox must be on the same host as the stream and
is a mailbox of the type of the source mailbox only.
The flags for mail_search_full() are a bit mask with one or more
of the following:
CP_UID The sequence argument contains UIDs instead of
sequence numbers
CP_MOVE Delete the messages from the current mailbox
after copying to the destination.
long mail_append (MAILSTREAM *stream,char *mailbox,STRING *message);
long mail_append_full (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
STRING *message);
stream stream to use if non-NIL (in the IMAP case)
mailbox destination mailbox name
flags flags to set on message if non-NIL
date internal date (received date) to set on message if non-NIL
message string structure of message to write
This function writes the message in the string structure to the
destination mailbox, along with the flags and date if specified. This
is useful in those cases where you can't use mail_copy(), e.g. when
copying from one server to another; you can always fetch the message
and then mail_append() it to the destination. It may also be useful
for maintaining an outbox of your outgoing mail.
void mail_gc (MAILSTREAM *stream,long gcflags);
stream stream to GC if non-NIL (else GC's all streams)
flags option flags
This function garbage collects (purges) the cache of entries of
a specific type. Some drivers do not allow purging of particular
cache types, and an attempt to do so is ignored.
The flags for mail_gc() are a bit mask with one or more of the
following:
GC_ELT message cache elements
GC_ENV ENVELOPEs and BODYs
GC_TEXTS cached texts
Date/Time Handling Functions
char *mail_date (char *string,MESSAGECACHE *elt);
string destination string
elt message cache element containing date
This function accepts a message cache element that contains date
information, and writes an IMAP-4 date string, that is, one in form:
dd-mmm-yyyy hh:mm:ss +zzzz
based upon the data in the elt. The destination string must be large
enough to hold this string.
char *mail_cdate (char *string,MESSAGECACHE *elt);
string destination string
elt message cache element containing date
This function accepts a message cache element that contains date
information, and writes a ctime() format date string, that is, one in
form:
www mmm dd hh:mm:ss yyyy\n
based upon the data in the elt. The destination string must be large
enough to hold this string.
long mail_parse_date (MESSAGECACHE *elt,char *string);
elt message cache element to store parsed date
string source date string
This function parses the date/time stored in the given string,
in format:
[www,] date [[hh:mm[:ss][-zzz| +zzzz]
where the date can be any of:
mm/dd/yy, mm/dd/yyyy, dd-mmm-yy, dd-mmm-yyyy, dd mmm yy, dd mmm yyyy
and stores the result of the parse in the elt. If the parse is
successful, T is returned, else NIL.
unsigned long mail_longdate (MESSAGECACHE *elt);
elt message cache element containing date.
This function accepts a message cache element that contains date
information, and returns the number of days since the base time of the
imap-4 toolkit. At present, this is the same as the Unix time() value
for that date/time, and hence can be used for functions such as utime().
Utility Functions
void mail_debug (MAILSTREAM *stream);
stream stream to debug
This function enables telemetry logging for this stream. All
telemetry is passed to the application via the mm_dlog() facility.
void mail_nodebug (MAILSTREAM *stream);
stream stream to disable debugging
This function disables telemetry logging for this stream.
long mail_sequence (MAILSTREAM *stream,char *sequence);
stream stream to set the sequence bits
sequence IMAP-format message set string
This function parses the given sequence string for message
numbers, sets the sequence bit in the stream's message cache element
of all messages in the sequence (and turns it off in all other message
cache elements). If the parse is successful, T is returned, else NIL.
long mail_uid_sequence (MAILSTREAM *stream,char *sequence);
stream stream to set the sequence bits
sequence IMAP-format message set string
This function parses the given sequence string for unique
identifiers, sets the sequence bit in the stream's message cache
element of all messages in the sequence (and turns it off in all other
message cache elements). If the parse is successful, T is returned,
else NIL.
long mail_parse_flags (MAILSTREAM *stream,char *flag,unsigned long *uf);
stream stream (used to get user flags)
flag IMAP-format flag string to parse
uf returned location of user flags
The function parses the given flag string, and returns the system
flags as its return value and the user flags in the location pointed
to by the uf argument. If there is an error in parse, a log message
is issued via mm_log() and this function returns NIL.
unsigned long mail_filter (char *text,unsigned long len,STRINGLIST *lines,
long flags);
text RFC 822 text to filter
len length in octets in the text argument
lines string list of header file names to filter
flags option flags
This function supports the header lines filtering function of
mail_fetchheader_full(). The lines argument contains a list of header
field names to use in subsetting the header text. Only those lines
which have that header field name are returned, unless FT_NOT is set
in which case only those lines which do not have that header field
name are returned.
The options for mail_filter() are a bit mask with one or more of
the following:
FT_NOT The returned header lines are those that are
not in the lines argument
long mail_search_msg (MAILSTREAM *stream,unsigned long msgno,char *charset,
SEARCHPGM *pgm);
stream stream to search
msgno message number of message to inspect
charset character set of search strings
pgm search program to test
This function implements mail_search_full() locally in cases when
it is not done by a server (e.g. local mail files, NNTP/POP). It
inspects the given message on that stream to see if it matches the
criteria or not. If it matches, T is returned, else NIL.
SEARCHPGM *mail_criteria (char *criteria);
criteria IMAP2-format search criteria string
This function accepts an IMAP2-format search criteria string and
parses it. If the parse is successful, it returns a search program
suitable for use in mail_search_full().
WARNING: This function does not accept IMAP4 search criteria.
The source string must be writeable (this restriction was also
in the old IMAP2 c-client).
Data Structure Instantiation/Destruction functions
These functions are used to obtain structures from free storage and
to release them.
ENVELOPE *mail_newenvelope (void);
ADDRESS *mail_newaddr (void);
BODY *mail_newbody (void);
BODY *mail_initbody (BODY *body);
PARAMETER *mail_newbody_parameter (void);
PART *mail_newbody_part (void);
STRINGLIST *mail_newstringlist (void);
SEARCHPGM *mail_newsearchpgm (void);
SEARCHHEADER *mail_newsearchheader (char *line);
SEARCHSET *mail_newsearchset (void);
SEARCHOR *mail_newsearchor (void);
SEARCHPGMLIST *mail_newsearchpgmlist (void);
SORTPGM *mail_newsortpgm (void);
These functions, all named mail_new...(), create a new structure of
the given type and initialize all of its elements to zero or empty.
void mail_free_body (BODY **body);
void mail_free_body_parameter (PARAMETER **parameter);
void mail_free_body_part (PART **part);
void mail_free_cache (MAILSTREAM *stream);
void mail_free_elt (MESSAGECACHE **elt);
void mail_free_lelt (LONGCACHE **lelt);
void mail_free_envelope (ENVELOPE **env);
void mail_free_address (ADDRESS **address);
void mail_free_stringlist (STRINGLIST **string);
void mail_free_searchpgm (SEARCHPGM **pgm);
void mail_free_searchheader (SEARCHHEADER **hdr);
void mail_free_searchset (SEARCHSET **set);
void mail_free_searchor (SEARCHOR **orl);
void mail_free_searchpgmlist (SEARCHPGMLIST **pgl);
void mail_free_sortpgm (SORTPGM **pgm);
These functions, all named mail_free_...(), take a pointer to a
structure pointer, free all contained strings and structures within the
structure, and finally free the structure itself and set its pointer to
NIL. For example, mail_free_envelope() frees all the ADDRESS structures
contained in the envelope.
Normally, mail_free_elt() and mail_free_lelt() are used only if the
main program has a private pointer to cache elements. If so, it is
expected to increment the cache element's lockcount when it makes a
private pointer, and to call this function when it is finished with it.
Authentication Functions
char *mail_auth (char *mechanism,authresponse_t resp,int argc,char *argv[]);
mechanism authentication mechanism name
resp callback function for providing responses
argc main() function argc value
argv main() function argv value
This server function searches the list of authenticators that was
established by auth_link() for an authenticator with the given name. If
an authenticator is found, authentication is initialized. The function
pointed to by resp is called as the authenticator requires responses.
AUTHENTICATOR *mail_lookup_auth (unsigned int i);
i position in authenticator list
This function returns the nth authenticator in the list, where n is
the value of it.
unsigned int mail_lookup_auth_name (char *mechanism);
mechanism authentication mechanism name
This function searches the list of authenticators for an
authenticator with the given name, and returns its position in the
authenticator list.
The functions below are provided by c-client client drivers or by
servers to support the protocol-dependent parts of authentication.
typedef void *(*authchallenge_t) (void *stream,unsigned long *len);
stream stream to read challenge
len pointer to returned length in octets
This driver function is called by an authenticator to read a
challenge from the given protocol stream in a protocol-dependent way.
It returns that challenge in binary and its length in octets to the
authenticator.
typedef long (*authrespond_t) (void *stream,char *s,unsigned long size);
stream stream to send response
s response string
size length of response string in octets
This driver function is called by an authenticator to send a
challenge response to the given stream in a protocol-dependent way.
It returns T if successful, NIL if failure.
typedef char *(*authresponse_t) (void *challenge,unsigned long clen,
unsigned long *rlen);
challenge challenge string
clen length of challenge string in octets
rlen pointer to returned length of response string
This server function is called with a challenge string of clen
octets. It sends, according to whatever protocol (IMAP, POP, etc.) it
uses, and returns the received response and response length in octets.
typedef long (*authclient_t) (authchallenge_t challenger,
authrespond_t responder,NETMBX *mb,void *s,
unsigned long trial);
challenger pointer to protocol-dependent challenge reader function
responder pointer to protocol-dependent response sender function
mb NETMBX struct of the mailbox desired to open
s stream for protocol-dependent routines to use
trial number of authentication attempts remaining
This client authenticator function negotiates reading challenges
and sending responses for a particular authenticator (Kerberos, etc.)
over the protocol, and returns T if authenticated or NIL if failed.
typedef char *(*authserver_t) (authresponse_t responder,int argc,char *argv[]);
responder pointer to protocol-dependent responder function
argc main() function argc value
argv main() function argv value
This server authenticator function negotiates sending challenges and
reading responses for a particular authenticator (Kerberos, etc.), and
returns either the authenticated user name or NIL if authentication
failed.
Network Access Functions
These functions provide a layer of indirection between the TCP
routines and upper level routines. This makes it possible to insert
additional code (e.g. privacy or checksum handling).
NETSTREAM *net_open (char *host,char *service,unsigned long port);
host host name
service contact service name
port contact port number
This function opens a TCP connection to the given host and service
or port.
NETSTREAM *net_aopen (NETMBX *mb,char *service,char *usrbuf);
NETMBX parsed mailbox specification
service stream to open (at present, only /etc/rimapd is used)
usrbuf buffer to return login user name
This function attempts to open a preauthenticated connection to the
given mailbox and service. It will return the login user name of the
preauthenticated connection, as well as an open network stream, if
successful.
char *net_getline (NETSTREAM *stream);
stream network stream to read
This routine reads a text line from the stream. It calls
stream->dtb->getline, which normally points to tcp_getline() but can be
set to some other function.
long net_getbuffer (void *stream,unsigned long size,char *buffer);
stream network stream to read
size length of data in octets
buffer buffer of at least size octets
This routine reads data from the stream. It calls
stream->dtb->getbuffer, which normally points to tcp_getbuffer() but can
be set to some other function.
long net_soutr (NETSTREAM *stream,char *string);
stream network stream to write
string null-terminated string to output
This routine writes a null-terminated string to the stream. It
calls stream->dtb->soutr, which normally points to tcp_soutr() but can
be set to some other function.
long net_sout (NETSTREAM *stream,char *string,unsigned long size);
stream network stream to write
string string to output
size length of string in octets
This routine writes a string of length size to the stream. It
calls stream->dtb->sout, which normally points to tcp_sout() but can be
set to some other function.
void net_close (NETSTREAM *stream);
stream stream to close
This routine closes the stream. It calls stream->dtb->close, which
normally points to tcp_close() but can point to some other function.
char *net_host (NETSTREAM *stream);
stream stream to inspect
This routine returns the remote host name of the stream. It calls
stream->dtb->host, which normally points to tcp_host() but can point
to some other function.
unsigned long net_port (NETSTREAM *stream);
stream stream to inspect
This routine returns the remote port number of the stream. It calls
stream->dtb->port, which normally points to tcp_port() but can point
to some other function.
char *net_localhost (NETSTREAM *stream);
stream stream to inspect
This routine returns the local host name of the stream. It calls
stream->dtb->localhost, which normally points to tcp_localhost() but can
point to some other function.
Subscription Management Functions
long sm_subscribe (char *mailbox);
mailbox mailbox name to subscribe
This function adds the given mailbox name to the local subscription
list, and returns T if successful, NIL if failure.
long sm_unsubscribe (char *mailbox);
mailbox mailbox name to unsubscribe
This function removes the given mailbox name from the local
subscription list, and returns T if successful, NIL if failure.
char *sm_read (void **sdb);
sdb data to use in subsequent calls, or NIL if first call
This function returns the local subscription list as null
terminated strings. Each call returns the next element in the list.
The first call should be with sdb pointing to a NIL pointer; this will
be filled in for subsequent calls. At the last call, NIL will be
returned.
Miscellaneous Utility Functions
char *ucase (char *string);
string string to convert
This function converts each lowercase character of the specified
string to uppercase and returns the string.
char *lcase (char *string);
string string to convert
This function converts each uppercase character of the specified
string to lowercase and returns the string.
char *cpystr (char *string);
string string to copy
This function makes a copy of the string from free storage and returns
the copy.
long find_rightmost_bit (long *valptr);
valptr pointer to value to search
This function returns -1 if the 32-bit value pointed to by valptr
is non-zero, otherwise it returns the bit number (0 = LSB, 31 = MSB) of
the right-most bit in that value. This is used to convert from the bits
in the cache's userflags item to an index into the stream's userFlags
array of flag texts.
long min (long i,long j);
i first argument
j second argument
This function returns the minimum of the two integers.
long max (long i,long j);
i first argument
j second argument
This function returns the maximum of the two integers.
long search (char *s,long c,char *pat,long patc);
s string to search
c size of string
pat pattern to search in string
patc size of pattern
This function does a fast case-independent search for the given
pattern in pat (length patc) in base string s, and returns T if the
pattern is found in the string.
long pmatch (char *s,char *pat,delim);
long pmatch_full (char *s,char *pat,delim);
s string to match
pat wildcard (* and %) to match in pattern
delim hierarchy delimiter
This function returns T if the given wildcard pattern matches the
string in s with hierarchy delimiter delim. Otherwise NIL is returned.
long dmatch (char *s,char *pat,char delim);
s string to match
pat wildcard (* and %) to match in pattern
delim hierarchy delimiter
This function returns T if the given wildcard pattern matches the
directory. If not, then none of the elements in the directory are
considered for recursive checking with pmatch_full().
SMTP Functions
SMTPSTREAM *smtp_open (char **hostlist,long debug);
hostlist vector of SMTP server host names to try
debug non-zero if want protocol telemetry debugging
This function opens an SMTP connection to a one of the hosts in the
host list and if successful returns a stream suitable for use by the
other SMTP functions. The hosts are tried in order until a connection is
successfully opened. If debug is non-NIL, protocol telemetry is logged
via mm_dlog(). NIL is returned if this function fails to open a
connection to any of the hosts in the list.
void smtp_close (SMTPSTREAM *stream);
stream stream to close
This function closes the SMTP stream and frees all resources
associated with it that it may have created.
long smtp_mail (SMTPSTREAM *stream,char *type,ENVELOPE *msg,BODY *body);
stream stream to transmit mail
type mail type (MAIL, SEND, SAML, SOML)
msg message envelope
body message body
This function negotiates an SMTP transaction of the specified type
(one of "MAIL", "SEND", "SAML", or "SOML") to deliver the specified
message. This function returns T if success or NIL if there is any
failure. The text reason for the failure is in stream->reply item; if
it is associated with a recipient it is also in that address'
address->error item.
void smtp_debug (SMTPSTREAM *stream);
stream stream to enable debugging telemetry
This function enables SMTP protocol telemetry logging for this
stream. All SMTP protocol operations are passed to the application via
the mm_dlog() facility.
void smtp_nodebug (SMTPSTREAM *stream);
stream stream to disable debugging telemetry
This function disables SMTP protocol telemetry logging for this
stream.
typedef void (*smtpverbose_t) (char *buffer);
buffer pointer to verbose reply buffer
This is the argument to the SET_SMTPVERBOSE mail_parmameter() call.
If this function pointer is non-NIL, then if a verbose SMTP response
(with SMTP code less than 100) is received, this function is called with
that response text as its argument.
NNTP Functions
NNTPSTREAM *nntp_open (char **hostlist,long debug);
hostlist vector of NNTP server host names to try
debug non-zero if want protocol telemetry debugging
This function opens an NNTP connection to a one of the hosts in the
host list and if successful returns a stream suitable for use by the
other MTP functions. The hosts are tried in order until a connection is
successfully opened. If debug is non-NIL, protocol telemetry is logged
via mm_dlog(). NIL is returned if this function fails to open a
connection to any of the hosts in the list.
void nntp_close (NNTPSTREAM *stream);
stream stream to close
This function closes the NNTP stream and frees all resources
associated with it that it may have created.
long nntp_mail (NNTPSTREAM *stream,ENVELOPE *msg,BODY *body);
stream stream to transmit mail
msg message envelope
body message body
This function negotiates an NNTP posting transaction to deliver
the specified news message. This function returns T if success or NIL
if there is any failure. The text reason for the failure is in
stream->reply item; if it is associated with a recipient it is also in
that address' address->error item.
RFC 822 Support Functions
Although rfc822.c contains several additional functions besides
these, only the functions documented here should be used by
applications. The other functions are for internal use only.
void rfc822_header (char *header,ENVELOPE *env,BODY *body);
header buffer to write RFC 822 header
env message ENVELOPE (used to obtain RFC 822 information)
body message BODY (used to obtain MIME information)
This function writes an RFC 822 format header into header based
on the information in the envelope and body. The header buffer must
be large enough to contain the full text of the resulting header.
void rfc822_write_address (char *dest,ADDRESS *adr);
dest buffer to write address list
adr RFC 822 ADDRESS list
This function writes an RFC 822 format address list into dest
based on the information in adr. The dest buffer must be large enough
to contain the full text of the resulting address list.
void rfc822_parse_msg (ENVELOPE **en,BODY **bdy,char *s,unsigned long i,
STRING *b,char *host,char *tmp);
en destination pointer where message ENVELOPE will be stored
bdy destination pointer where message BODY will be stored
s RFC 822 header to parse (character string)
i length of RFC 822 header
b stringstruct of message body
host default host name if an address lacks an @host.
temp scratch buffer, must be long enough to hold unwound
header lines (a buffer that is i octets long is OK)
This function parses the RFC 822 header pointed to by s with body
pointed to by string structure b into the specified destination
envelope and body pointers, using host as the default host name and
tmp as a scratch buffer. New ENVELOPE and BODY structures are
created; when finished with them the application must free them with
mail_free_envelope() and mail_free_body(). Any parsing errors are
noted via the mm_log() mechanism using log type PARSE.
void rfc822_parse_adrlist (ADDRESS **lst,char *string,char *host);
lst destination pointer where ADDRESS will be stored
string string of addresses to parse
host default host name if an address lacks an @host.
This function parses the address list in the given string into an
address list in lst. Any addresses missing a host name are have the
host name defaulted from the host argument. If the destination list
is non-empty it appends the new addresses to the list. Any parsing
errors are noted via the mm_log() mechanism using log type PARSE.
long rfc822_output (char *t,ENVELOPE *env,BODY *body,soutr_t f,void *s,
long ok8bit);
t scratch buffer, large enough to hold message header
env message ENVELOPE
body message BODY
f I/O function to write to
s stream for I/O function f
ok8bit non-zero if OK to output 8-bit data
This function writes the message described with the given
envelope and body. Any body part contents of type ENCBINARY is
converted to ENCBASE64 before sending. If ok8bit is NIL, any message
data of type ENC8BIT is converted to ENCQUOTEDPRINTABLE before
sending; if ok8bit is non-NIL then ENC8BIT data is sent as-is. T is
returned if the function succeeds, else NIL is returned.
The function f is typically net_soutr(), but it can be any
function which matches
typedef long (*soutr_t) (void *stream,char *string);
where stream holds sufficient information to enable the output routine
to know where to output to, and the string is a null-terminated string
to output. This function returns either T or NIL, and that value is
passed up to rfc822_output() for its return.
void *rfc822_base64 (char *src,unsigned long srcl,unsigned long *len);
src source string
srcl size of source string in octets
len pointer to where destination string length in octets
will be returned
This function decodes a BASE64 body part given a source string
and its length. The decoded body part as a sequence of binary octets
is returned, and its length is returned in len.
char *rfc822_qprint (char *src,unsigned long srcl,unsigned long *len);
src source string
srcl size of source string in octets
len pointer to where destination string length in octets
will be returned
This function decodes a QUOTED-PRINTABLE body part given a source
string and its length. The decoded body part as an 8-bit character
string is returned, and its length is returned in len.
Operating System-Dependent Public Interface
These functions are in OS-dependent code, and are rewritten each
time c-client is ported to a new operating system.
void rfc822_date (char *date);
date buffer to write the date, must be large enough
This function is called to get the current date and time in an
RFC 822 format string into the given buffer.
void *fs_get (size_t size);
size number of octets requested
This function allocates and returns a block of free storage of
the specified size. Unlike malloc(), there is no failure return; this
function must return with the requested storage.
void fs_resize (void **block,size_t size);
block pointer to pointer to block to be resized
size new size in octets
This function resizes the free storage block, updating the
pointer if necessary. Unlike realloc(), there is no failure return;
this function must return with the requested storage.
void fs_give (void **block);
block pointer to pointer to block to free
This function releases a block of free storage allocated by
fs_get(). It also erases the block pointer, so it isn't necessary to
do this in the application.
void fatal (char *string);
string message string
This function is called when an "impossible" error is detected
and the client wishes to crash. The string should contain a reason.
char *strcrlfcpy (char **dst,long *dstl,char *src,long srcl);
dst pointer to destination string pointer
dstl pointer to destination string size
src source strin
srcl source string size
This function is called to copy into a destination string dst of
size dstl (resized if necessary), a CRLF newline form string from
local format string src of size srcl.
TCPSTREAM *tcp_open (char *host,long port);
TCPSTREAM *tcp_aopen (char *host,char *service);
char *tcp_getline (TCPSTREAM *stream);
long tcp_getbuffer (TCPSTREAM *stream,long size,char *buffer);
long tcp_soutr (TCPSTREAM *stream,char *string);
void tcp_close (TCPSTREAM *stream);
char *tcp_host (TCPSTREAM *stream);
unsigned long tcp_port (TCPSTREAM *stream);
char *tcp_localhost (TCPSTREAM *stream);
These functions are TCP-specific versions of the more general
net_xxx() functions. These should not be called directly by
applications.
char *tcp_clienthost (char *dst);
dst destination string buffer
This function should be called only by a server called by inetd
or similar mechanism which maps standard input to a network socket.
It returns the host name of the other end (e.g. the client of a
server) using the given string buffer, or NIL if it can't get this
information.
Main Program Callbacks
All applications which use the c-client must have the following
callbacks to handle events from c-client. Note that in any callback
which involves a mail stream, the stream is locked and you can not
recursively call c-client from the callback. This may also be true in
callbacks which do not have a stream; in general, the rule is "do not
call c-client, especially any mail_xxx() function, from a c-client
callback".
void mm_flags (MAILSTREAM *stream,unsigned long number);
stream stream where event happened
number message number
This function is called when c-client manipulates the flags for
the given message number. This alerts the application that it may
need to inspect that message's flags to see if there are any
interesting changes.
void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status);
stream stream where event happened
mailbox mailbox name for this status
status MAILSTATUS structure with message status
This function is called when c-client reports status of a mailbox
(generally as the result of a mail_status() function call). The
returned MAILSTATUS structure has the following members:
long flags; validity flags. These are the same as
the SA_xxx option flags in the
mail_status() call, and they indicate
which of the other members of the
MAILSTATUS structure have usable data
(i.e. if SA_MESSAGES is not set, do
not believe status->messages!!).
unsigned long messages; number of messages if SA_MESSAGES
unsigned long recent; number of recent messages if SA_RECENT
unsigned long unseen; number of unseen messages if SA_UNSEEN
unsigned long uidnext; next UID to be assigned if SA_UIDNEXT
unsigned long uidvalidity; UID validity value if SA_UIDVALIDITY
void mm_searched (MAILSTREAM *stream,unsigned long number);
stream stream where event happened
number message number
This function is called to notify the main program that this
message number matches a search (generally as the result of a
mail_search_full() function call).
void mm_exists (MAILSTREAM *stream,unsigned long number);
stream stream where event happened
number message number
This function is called to notify the main program that there are
this many messages in the mailbox. It is also used to notify the main
program of new mail, by announcing a higher number than the main
program was previously aware.
void mm_expunged (MAILSTREAM *stream,unsigned long number);
stream stream where event happened
number message number
This function is called to notify the main program that this
message number has been expunged from the mail file and that all
subsequent messages are now referenced by a message number one less
than before. This implicitly decrements the number of messages in the
mailbox.
void mm_list (MAILSTREAM *stream,char delim,char *name,long attrib);
stream stream where event happened
delim hierarchy delimiter
name mailbox name
attrib mailbox attributes
This function is called to notify the main program that this
mailbox name matches a mailbox listing request (generally as the
result of a mail_list() function call). The hierarchy delimiter is a
character that separates out levels of hierarchy in mailbox names.
The attributes are a bit mask with one of the following:
LATT_NOINFERIORS
it is not possible for there to be any
hierarchy inferiors to this name (that is,
this name followed by the hierarchy delimiter
and additional name characters).
LATT_NOSELECT this is not a mailbox name, just a hierarchy
level, and it may not be opened by mail_open()
LATT_MARKED this mailbox may have recent messages
LATT_UNMARKED this mailbox does not have any recent messages
void mm_lsub (MAILSTREAM *stream,char delim,char *name,long attrib);
stream stream where event happened
delim hierarchy delimiter
name mailbox name
attrib mailbox attributes
This function is called to notify the main program that this
mailbox name matches a subscribed mailbox listing request (generally
as the result of a mail_lsub() function call). The hierarchy
delimiter is a character that separates out levels of hierarchy in
mailbox names. The attributes are a bit mask with one of the
following:
LATT_NOINFERIORS
it is not possible for there to be any
hierarchy inferiors to this name (that is,
this name followed by the hierarchy delimiter
and additional name characters).
LATT_NOSELECT this is not a mailbox name, just a hierarchy
level, and it may not be opened by mail_open()
LATT_MARKED this mailbox may have recent messages
LATT_UNMARKED this mailbox does not have any recent messages
void mm_notify (MAILSTREAM *stream,char *string,long errflg);
stream stream where event happened
string message string
errflg message error level
This function is called to deliver a stream-oriented message
event. This is the mechanism by which any IMAP response codes for any
application (e.g. TRYCREATE) are delivered to the application.
No newline is included in the string, so this function has to output
its own.
The message error level is one of the following:
NIL normal operation. The text is `babble' that may be
interesting to the user, e.g. the greeting message
from a server.
WARN A warning event. This event should be displayed to
the user. Examples: a mailbox rewrite failed because
of disk full, but the previous mailbox contents were
recovered.
ERROR An error event. This event should be displayed to
the user, or at least logged someplace. This type of
error shouldn't happen, and so should be called to the
attention of support staff. Whatever happened has
probably disrupted the user's work. Examples: an
untagged BAD from an IMAP server.
void mm_log (char *string,long errflg);
string message string
errflg message error level
This function is called to deliver a log message. No newline is
included in the string, so this function has to output its own. In
general, it is intended that these messages are logged someplace, and
possibly shown to the user.
The message error level is one of the following:
NIL normal operation. The text is `babble' that may be
interesting to the user, e.g. "Expunged 3 messages".
PARSE An RFC 822 parsing error. Since bogus headers are
all-too-common in the real world, these can often be
ignored on the "garbage in, garbage out" princple.
However, since surprising results can be yielded when
trying to parse garbage, this message should be logged
somewhere so it can be figured out what happened.
WARN A warning event. This event should be displayed to
the user. It occurs when an error condition has
happened, but c-client knows what to do to recover.
Examples: "Can't open read-write, so opening
read-only", "Empty mailbox", "Login failed, try
again", "Waiting for mailbox to become unlocked",
"IMAP protocol error". Although a user should be
told about a warning, it's generally not necessary
to interrupt the flow of her work (e.g. it's alright
to display the warning in a scrolling window, but
not necessary to require the user to do anything).
ERROR An error event. This event should be displayed to
the user, or at least logged someplace. This is a
serious error condition occured that aborted the
requested operation and possibly also aborted the mail
stream. This ranges from normal error conditions such
as "Can't open mailbox", "too many login failures, go
away" to bizarre conditions such as "Apparent new mail
appeared in the mailbox that doesn't look like mail,
program aborting". Errors must be called to the
user's attention, and probably should require some
sort of acknowledgement (e.g. answering a modal panel)
before the application proceeds.
void mm_dlog (char *string);
string message string
This function is called to deliver a debugging telemetry
message. No newline is included in the string, so this function has
to output its own. This is called only when debugging is enabled.
void mm_login (NETMBX *mb,char *user,char *pwd,long trial);
mb parsed mailbox specification
user pointer to where to return user name
pwd pointer to where to return password
trial number of prior login attempts
This function is called to get a user name and password for the
given network mailbox. It stores the user name and password in the
strings pointed to by the appropriate arguments. The trial argument
is the number of attempts to perform the login and is initially zero
(e.g. for a default username and password login functionality). It is
incremented for each subsequent trial until the maximum number of
trials are made.
void mm_critical (MAILSTREAM *stream);
stream stream where event happened
This function is called to alert the application that c-client
is about to run some critical code on that stream that may result in a
clobbered mail file if it is interrupted. It may be desirable to
disable CTRL/C, etc. during this time.
void mm_nocritical (MAILSTREAM *stream);
stream stream where event happened
This function is called to alert the application that c-client
is no longer running critical code on that stream that may result in a
clobbered mail file if it is interrupted.
long mm_diskerror (MAILSTREAM *stream,long errcode,long serious);
stream stream where event happened
errcode OS error code for disk error
serious non-zero if c-client can not undo the operation (and
thus must retry to avoid mail file damage)
This function is called to alert the application that the
c-client has encountered an unrecoverable write error when trying to
update the mail file. errcode contains the system error code. If
serious is non-zero, then it is probable that the disk copy of the
mailbox has been damaged.
The return value from this function is the abort flag; if serious
is zero and the abort flag is non-zero, the operation is aborted. If
the abort flag is zero or if serious was non-zero, a return from this
function will retry the failing operation.
void mm_fatal (char *string);
string message string
This function is called from the fatal() routine in the
operating system code to notify the main program that it is about to
crash. The string contains a reason. At the very minimum, the main
program should do something like
mm_log (string,ERROR);
and then return. No newline is included in the string, so this
function has to output its own.
Driver interface
When writing a new driver for the c-client, you must provide a
DRIVER stucture giving a dispatch vector between MAIL and the driver.
The DRIVER dispatch vector is described in mail.h.
char *name;
Name by which the driver is known to c-client.
unsigned long flags;
Attribute flags for this driver:
DR_DISABLE This driver is currently disabled.
DR_LOCAL This driver deals with local mailboxes; if
this is off it deals with mailboxes over a
network.
DR_MAIL This driver supports e-mail messages.
DR_NEWS This driver supports netnews messages
DR_READONLY This driver only allows read-only access;
mail_setflag(), mail_expunge(), etc. are
no-ops.
DR_NOFAST This driver does not implement mail_fetchfast()
in a fast way (e.g. it may have to fetch the
entire message text over a network to
calculate sizes).
DR_NAMESPACE This driver accepts and uses namespace format
names.
DR_LOWMEM This driver is designed for systems with very
limited amounts of memory (e.g. DOS) and
support routines called by this driver should
try not to use much memory.
DRIVER *next;
Pointer to the next driver which this application supports (or NIL if
this is the last driver). Drivers are lunk together via the mail_link()
function.
DRIVER *driver_valid (char *mailbox);
This function returns a pointer to the driver's DRIVER dispatch
vector iff this driver accepts the given name as a valid mailbox for this
driver. Otherwise, it returns the value of the next driver's
driver_valid() or NIL if there is no next driver. In other words, calling
driver_valid() for the first driver will return the driver dispatch vector
for the driver which supports this type of mailbox.
void *driver_parameters (long function,void *value);
This function implements mail_parameters() for this driver.
void driver_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);
This function implements mail_scan() for this driver.
void driver_list (MAILSTREAM *stream,char *ref,char *pat);
This function implements mail_list() for this driver.
void driver_lsub (MAILSTREAM *stream,char *ref,char *pat);
This function implements mail_lsub() for this driver.
long driver_subscribe (MAILSTREAM *stream,char *mailbox);
This function implements mail_subscribe() for this driver.
long driver_unsubscribe (MAILSTREAM *stream,char *mailbox);
This function implements mail_unsubscribe() for this driver.
long driver_create (MAILSTREAM *stream,char *mailbox);
This function implements mail_create() for this driver.
long driver_delete (MAILSTREAM *stream,char *mailbox);
This function implements mail_delete() for this driver.
long driver_rename (MAILSTREAM *stream,char *old,char *new);
This function implements mail_rename() for this driver.
long driver_status (MAILSTREAM *stream,char *mailbox,long flags);
This function implements mail_status() for this driver.
MAILSTREAM *driver_open (MAILSTREAM *stream);
This function opens the mailbox identified by the given stream. It
may use the data on the stream and create additional data on stream->local
as necessary. It should return the given stream unless it failed to open
the mailbox, in which case it should return NIL.
void driver_close (MAILSTREAM *stream,long options);
This function implements mail_close() for this driver.
void driver_fetchfast (MAILSTREAM *stream,char *sequence,long flags);
This function implements mail_fetchfast() for this driver.
void driver_fetchflags (MAILSTREAM *stream,char *sequence,long flags);
This function implements mail_fetchflags() for this driver.
ENVELOPE *driver_fetchstructure (MAILSTREAM *stream,unsigned long msgno,
BODY **body,long flags);
This function implements mail_fetchstructure() for this driver.
char *driver_fetchheader (MAILSTREAM *stream,unsigned long msgno,
STRINGLIST *lines,unsigned long *len,long flags);
This function implements mail_fetchheader() for this driver.
char *driver_fetchtext (MAILSTREAM *stream,unsigned long msgno,
unsigned long *len,long flags);
This function implements mail_fetchtext() for this driver.
char *driver_fetchbody (MAILSTREAM *stream,unsigned long msgno,char *section,
unsigned long *len,long flags);
This function implements mail_fetchbody() for this driver.
void driver_setflag (MAILSTREAM *stream,char *sequence,char *flag,long flags);
This function implements mail_setflag() for this driver.
void driver_clearflag (MAILSTREAM *stream,char *sequence,char *flag,
long flags);
This function implements mail_clearflag() for this driver.
void driver_search (MAILSTREAM *stream,char *charset,SEARCHPGM *pgm,
long flags);
This function implements mail_search() for this driver.
unsigned long *driver_sort (MAILSTREAM *stream,char *charset,SEARCHPGM *spg,
SORTPGM *pgm,long flags);
This function implements mail_sort() for this driver.
void *driver_thread (MAILSTREAM *stream,char *seq,long function,long flag);
This dispatch is reserved for a future threading capability.
long driver_ping (MAILSTREAM *stream);
This function implements mail_ping() for this driver.
void driver_check (MAILSTREAM *stream);
This function implements mail_check() for this driver.
void driver_expunge (MAILSTREAM *stream);
This function implements mail_expunge() for this driver.
long driver_copy (MAILSTREAM *stream,char *sequence,char *mailbox,
long options);
This function implements mail_copy() for this driver.
long driver_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
STRING *message);
This function implements mail_append() for this driver.
void driver_gc (MAILSTREAM *stream,long gcflags);
This function implements mail_gc() for this driver.
Driver Support Functions
void mail_searched (MAILSTREAM *stream,unsigned long msgno);
stream stream where event happened
msgno message number
This function is called by the driver to notify c-client that this
message number matches a search. It invokes the main program's
mm_searched() function.
void mail_exists (MAILSTREAM *stream,unsigned long nmsgs);
stream stream where event happened
nmsgs number of messages
This function is called by the driver to notify c-client that this
message number exists (i.e. there are this many messages in the mailbox).
It invokes the main program's mm_exists() function.
void mail_recent (MAILSTREAM *stream,unsigned long recent);
stream stream where event happened
recent number of messages
This function is called by the driver to notify c-client that this
many messages are "recent" (i.e. arrived in the mailbox since the previous
time the mailbox was opened).
void mail_expunged (MAILSTREAM *stream,unsigned long msgno);
stream stream where event happened
msgno number of messages
This function is called by the driver to notify MAIL that this
message number has been expunged from the mail file and that all subsequent
messages are now referenced by a message number one less than before. It
invokes the main program's mm_expunged() function.
void mail_lock (MAILSTREAM *stream);
stream stream where event happened
This function sets the stream lock. It is an error to set the stream
lock if the stream is already locked.
This is mainly used to catch errors due to a callback function
(e.g. mm_exists) inadvertantly recursing back to the MAIL routines and
establishing an infinite recursion. Normally, drivers will set the lock
prior to calling one of the callback functions above or, more likely, in
the beginning of the driver's non-reentrant "do operation" section. In the
IMAP4 driver, the stream lock is set when entering imap_send() and cleared
on exit.
void mail_unlock (MAILSTREAM *stream);
stream stream where event happened
This function releases the stream lock. It is an error to release the
stream lock if the stream is not locked.
|