imapext-2007

annotate src/mtest/mtest.c @ 0:ada5e610ab86

imap-2007e
author yuuji@gentei.org
date Mon, 14 Sep 2009 15:17:45 +0900
parents
children cd53ed0e4bb2
rev   line source
yuuji@0 1 /* ========================================================================
yuuji@0 2 * Copyright 1988-2007 University of Washington
yuuji@0 3 *
yuuji@0 4 * Licensed under the Apache License, Version 2.0 (the "License");
yuuji@0 5 * you may not use this file except in compliance with the License.
yuuji@0 6 * You may obtain a copy of the License at
yuuji@0 7 *
yuuji@0 8 * http://www.apache.org/licenses/LICENSE-2.0
yuuji@0 9 *
yuuji@0 10 *
yuuji@0 11 * ========================================================================
yuuji@0 12 */
yuuji@0 13
yuuji@0 14 /*
yuuji@0 15 * Program: Mail library test program
yuuji@0 16 *
yuuji@0 17 * Author: Mark Crispin
yuuji@0 18 * Networks and Distributed Computing
yuuji@0 19 * Computing & Communications
yuuji@0 20 * University of Washington
yuuji@0 21 * Administration Building, AG-44
yuuji@0 22 * Seattle, WA 98195
yuuji@0 23 * Internet: MRC@CAC.Washington.EDU
yuuji@0 24 *
yuuji@0 25 * Date: 8 July 1988
yuuji@0 26 * Last Edited: 5 November 2007
yuuji@0 27 *
yuuji@0 28 * This original version of this file is
yuuji@0 29 * Copyright 1988 Stanford University
yuuji@0 30 * and was developed in the Symbolic Systems Resources Group of the Knowledge
yuuji@0 31 * Systems Laboratory at Stanford University in 1987-88, and was funded by the
yuuji@0 32 * Biomedical Research Technology Program of the NationalInstitutes of Health
yuuji@0 33 * under grant number RR-00785.
yuuji@0 34 */
yuuji@0 35
yuuji@0 36 #include <stdio.h>
yuuji@0 37 #include <ctype.h>
yuuji@0 38 #include <signal.h>
yuuji@0 39 #include "c-client.h"
yuuji@0 40 #include "imap4r1.h"
yuuji@0 41
yuuji@0 42 /* Excellent reasons to hate ifdefs, and why my real code never uses them */
yuuji@0 43
yuuji@0 44 #ifndef unix
yuuji@0 45 # define unix 0
yuuji@0 46 #endif
yuuji@0 47
yuuji@0 48 #if unix
yuuji@0 49 # define UNIXLIKE 1
yuuji@0 50 # define MACOS 0
yuuji@0 51 # include <pwd.h>
yuuji@0 52 #else
yuuji@0 53 # define UNIXLIKE 0
yuuji@0 54 # ifdef noErr
yuuji@0 55 # define MACOS 1
yuuji@0 56 # include <Memory.h>
yuuji@0 57 # else
yuuji@0 58 # define MACOS 0
yuuji@0 59 # endif
yuuji@0 60 #endif
yuuji@0 61
yuuji@0 62 char *curhst = NIL; /* currently connected host */
yuuji@0 63 char *curusr = NIL; /* current login user */
yuuji@0 64 char personalname[MAILTMPLEN]; /* user's personal name */
yuuji@0 65
yuuji@0 66 static char *hostlist[] = { /* SMTP server host list */
yuuji@0 67 "mailhost",
yuuji@0 68 "localhost",
yuuji@0 69 NIL
yuuji@0 70 };
yuuji@0 71
yuuji@0 72 static char *newslist[] = { /* Netnews server host list */
yuuji@0 73 "news",
yuuji@0 74 NIL
yuuji@0 75 };
yuuji@0 76
yuuji@0 77 int main (void);
yuuji@0 78 void mm (MAILSTREAM *stream,long debug);
yuuji@0 79 void overview_header (MAILSTREAM *stream,unsigned long uid,OVERVIEW *ov,
yuuji@0 80 unsigned long msgno);
yuuji@0 81 void header (MAILSTREAM *stream,long msgno);
yuuji@0 82 void display_body (BODY *body,char *pfx,long i);
yuuji@0 83 void status (MAILSTREAM *stream);
yuuji@0 84 void prompt (char *msg,char *txt);
yuuji@0 85 void smtptest (long debug);
yuuji@0 86
yuuji@0 87 /* Main program - initialization */
yuuji@0 88
yuuji@0 89 int main ()
yuuji@0 90 {
yuuji@0 91 MAILSTREAM *stream = NIL;
yuuji@0 92 void *sdb = NIL;
yuuji@0 93 char *s,tmp[MAILTMPLEN];
yuuji@0 94 long debug;
yuuji@0 95 #include "linkage.c"
yuuji@0 96 #if MACOS
yuuji@0 97 {
yuuji@0 98 size_t *base = (size_t *) 0x000908;
yuuji@0 99 /* increase stack size on a Mac */
yuuji@0 100 SetApplLimit ((Ptr) (*base - (size_t) 65535L));
yuuji@0 101 }
yuuji@0 102 #endif
yuuji@0 103 curusr = cpystr (((s = myusername ()) && *s) ? s : "somebody");
yuuji@0 104 #if UNIXLIKE
yuuji@0 105 {
yuuji@0 106 char *suffix;
yuuji@0 107 struct passwd *pwd = getpwnam (curusr);
yuuji@0 108 if (pwd) {
yuuji@0 109 strcpy (tmp,pwd->pw_gecos);
yuuji@0 110 /* dyke out the office and phone poop */
yuuji@0 111 if (suffix = strchr (tmp,',')) suffix[0] = '\0';
yuuji@0 112 strcpy (personalname,tmp);/* make a permanent copy of it */
yuuji@0 113 }
yuuji@0 114 else personalname[0] = '\0';
yuuji@0 115 }
yuuji@0 116 #else
yuuji@0 117 personalname[0] = '\0';
yuuji@0 118 #endif
yuuji@0 119 curhst = cpystr (mylocalhost ());
yuuji@0 120 puts ("MTest -- C client test program");
yuuji@0 121 if (!*personalname) prompt ("Personal name: ",personalname);
yuuji@0 122 /* user wants protocol telemetry? */
yuuji@0 123 prompt ("Debug protocol (y/n)?",tmp);
yuuji@0 124 ucase (tmp);
yuuji@0 125 debug = (tmp[0] == 'Y') ? T : NIL;
yuuji@0 126 do {
yuuji@0 127 prompt ("Mailbox ('?' for help): ",tmp);
yuuji@0 128 if (!strcmp (tmp,"?")) {
yuuji@0 129 puts ("Enter INBOX, mailbox name, or IMAP mailbox as {host}mailbox");
yuuji@0 130 puts ("Known local mailboxes:");
yuuji@0 131 mail_list (NIL,NIL,"%");
yuuji@0 132 if (s = sm_read (&sdb)) {
yuuji@0 133 puts ("Local subscribed mailboxes:");
yuuji@0 134 do (mm_lsub (NIL,NIL,s,NIL));
yuuji@0 135 while (s = sm_read (&sdb));
yuuji@0 136 }
yuuji@0 137 puts ("or just hit return to quit");
yuuji@0 138 }
yuuji@0 139 else if (tmp[0]) stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
yuuji@0 140 } while (!stream && tmp[0]);
yuuji@0 141 mm (stream,debug); /* run user interface if opened */
yuuji@0 142 #if MACOS
yuuji@0 143 /* clean up resolver */
yuuji@0 144 if (resolveropen) CloseResolver ();
yuuji@0 145 #endif
yuuji@0 146 return NIL;
yuuji@0 147 }
yuuji@0 148
yuuji@0 149 /* MM command loop
yuuji@0 150 * Accepts: MAIL stream
yuuji@0 151 */
yuuji@0 152
yuuji@0 153 void mm (MAILSTREAM *stream,long debug)
yuuji@0 154 {
yuuji@0 155 void *sdb = NIL;
yuuji@0 156 char cmd[MAILTMPLEN];
yuuji@0 157 char *s,*arg;
yuuji@0 158 unsigned long i;
yuuji@0 159 unsigned long last = 0;
yuuji@0 160 BODY *body;
yuuji@0 161 status (stream); /* first report message status */
yuuji@0 162 while (stream) {
yuuji@0 163 prompt ("MTest>",cmd); /* prompt user, get command */
yuuji@0 164 /* get argument */
yuuji@0 165 if (arg = strchr (cmd,' ')) *arg++ = '\0';
yuuji@0 166 switch (*ucase (cmd)) { /* dispatch based on command */
yuuji@0 167 case 'B': /* Body command */
yuuji@0 168 if (arg) last = atoi (arg);
yuuji@0 169 else if (!last) {
yuuji@0 170 puts ("?Missing message number");
yuuji@0 171 break;
yuuji@0 172 }
yuuji@0 173 if (last && (last <= stream->nmsgs)) {
yuuji@0 174 mail_fetchstructure (stream,last,&body);
yuuji@0 175 if (body) display_body (body,NIL,(long) 0);
yuuji@0 176 else puts ("%No body information available");
yuuji@0 177 }
yuuji@0 178 else puts ("?Bad message number");
yuuji@0 179 break;
yuuji@0 180 case 'C': /* Check command */
yuuji@0 181 mail_check (stream);
yuuji@0 182 status (stream);
yuuji@0 183 break;
yuuji@0 184 case 'D': /* Delete command */
yuuji@0 185 if (arg) last = atoi (arg);
yuuji@0 186 else {
yuuji@0 187 if (last == 0) {
yuuji@0 188 puts ("?Missing message number");
yuuji@0 189 break;
yuuji@0 190 }
yuuji@0 191 arg = cmd;
yuuji@0 192 sprintf (arg,"%lu",last);
yuuji@0 193 }
yuuji@0 194 if (last && (last <= stream->nmsgs))
yuuji@0 195 mail_setflag (stream,arg,"\\DELETED");
yuuji@0 196 else puts ("?Bad message number");
yuuji@0 197 break;
yuuji@0 198 case 'E': /* Expunge command */
yuuji@0 199 mail_expunge (stream);
yuuji@0 200 last = 0;
yuuji@0 201 break;
yuuji@0 202 case 'F': /* Find command */
yuuji@0 203 if (!arg) {
yuuji@0 204 arg = "%";
yuuji@0 205 if (s = sm_read (&sdb)) {
yuuji@0 206 puts ("Local network subscribed mailboxes:");
yuuji@0 207 do if (*s == '{') (mm_lsub (NIL,NIL,s,NIL));
yuuji@0 208 while (s = sm_read (&sdb));
yuuji@0 209 }
yuuji@0 210 }
yuuji@0 211 puts ("Subscribed mailboxes:");
yuuji@0 212 mail_lsub (((arg[0] == '{') && (*stream->mailbox == '{')) ? stream : NIL,
yuuji@0 213 NIL,arg);
yuuji@0 214 puts ("Known mailboxes:");
yuuji@0 215 mail_list (((arg[0] == '{') && (*stream->mailbox == '{')) ? stream : NIL,
yuuji@0 216 NIL,arg);
yuuji@0 217 break;
yuuji@0 218 case 'G':
yuuji@0 219 mail_gc (stream,GC_ENV|GC_TEXTS|GC_ELT);
yuuji@0 220 break;
yuuji@0 221 case 'H': /* Headers command */
yuuji@0 222 if (arg) {
yuuji@0 223 if (!(last = atoi (arg))) {
yuuji@0 224 mail_search (stream,arg);
yuuji@0 225 for (i = 1; i <= stream->nmsgs; ++i)
yuuji@0 226 if (mail_elt (stream,i)->searched) header (stream,i);
yuuji@0 227 break;
yuuji@0 228 }
yuuji@0 229 }
yuuji@0 230 else if (last == 0) {
yuuji@0 231 puts ("?Missing message number");
yuuji@0 232 break;
yuuji@0 233 }
yuuji@0 234 if (last && (last <= stream->nmsgs)) header (stream,last);
yuuji@0 235 else puts ("?Bad message number");
yuuji@0 236 break;
yuuji@0 237 case 'L': /* Literal command */
yuuji@0 238 if (arg) last = atoi (arg);
yuuji@0 239 else if (!last) {
yuuji@0 240 puts ("?Missing message number");
yuuji@0 241 break;
yuuji@0 242 }
yuuji@0 243 if (last && (last <= stream->nmsgs))
yuuji@0 244 puts (mail_fetch_message (stream,last,NIL,NIL));
yuuji@0 245 else puts ("?Bad message number");
yuuji@0 246 break;
yuuji@0 247 case 'M':
yuuji@0 248 mail_status (NIL,arg ? arg : stream->mailbox,
yuuji@0 249 SA_MESSAGES|SA_RECENT|SA_UNSEEN|SA_UIDNEXT|SA_UIDVALIDITY);
yuuji@0 250 break;
yuuji@0 251 case 'N': /* New mailbox command */
yuuji@0 252 if (!arg) {
yuuji@0 253 puts ("?Missing mailbox");
yuuji@0 254 break;
yuuji@0 255 }
yuuji@0 256 /* get the new mailbox */
yuuji@0 257 while (!(stream = mail_open (stream,arg,debug))) {
yuuji@0 258 prompt ("Mailbox: ",arg);
yuuji@0 259 if (!arg[0]) break;
yuuji@0 260 }
yuuji@0 261 last = 0;
yuuji@0 262 status (stream);
yuuji@0 263 break;
yuuji@0 264 case 'O': /* Overview command */
yuuji@0 265 if (!arg) {
yuuji@0 266 puts ("?Missing UID");
yuuji@0 267 break;
yuuji@0 268 }
yuuji@0 269 mail_fetch_overview (stream,arg,overview_header);
yuuji@0 270 break;
yuuji@0 271 case 'P': /* Ping command */
yuuji@0 272 mail_ping (stream);
yuuji@0 273 status (stream);
yuuji@0 274 break;
yuuji@0 275 case 'Q': /* Quit command */
yuuji@0 276 mail_close (stream);
yuuji@0 277 stream = NIL;
yuuji@0 278 break;
yuuji@0 279 case 'S': /* Send command */
yuuji@0 280 smtptest (debug);
yuuji@0 281 break;
yuuji@0 282 case '\0': /* null command (type next message) */
yuuji@0 283 if (!last || (last++ >= stream->nmsgs)) {
yuuji@0 284 puts ("%No next message");
yuuji@0 285 break;
yuuji@0 286 }
yuuji@0 287 case 'T': /* Type command */
yuuji@0 288 if (arg) last = atoi (arg);
yuuji@0 289 else if (!last) {
yuuji@0 290 puts ("?Missing message number");
yuuji@0 291 break;
yuuji@0 292 }
yuuji@0 293 if (last && (last <= stream->nmsgs)) {
yuuji@0 294 STRINGLIST *lines = mail_newstringlist ();
yuuji@0 295 STRINGLIST *cur = lines;
yuuji@0 296 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
yuuji@0 297 cpystr ("Date")));
yuuji@0 298 cur = cur->next = mail_newstringlist ();
yuuji@0 299 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
yuuji@0 300 cpystr ("From")));
yuuji@0 301 cur = cur->next = mail_newstringlist ();
yuuji@0 302 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
yuuji@0 303 cpystr (">From")));
yuuji@0 304 cur = cur->next = mail_newstringlist ();
yuuji@0 305 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
yuuji@0 306 cpystr ("Subject")));
yuuji@0 307 cur = cur->next = mail_newstringlist ();
yuuji@0 308 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
yuuji@0 309 cpystr ("To")));
yuuji@0 310 cur = cur->next = mail_newstringlist ();
yuuji@0 311 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
yuuji@0 312 cpystr ("cc")));
yuuji@0 313 cur = cur->next = mail_newstringlist ();
yuuji@0 314 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
yuuji@0 315 cpystr ("Newsgroups")));
yuuji@0 316 printf ("%s",mail_fetchheader_full (stream,last,lines,NIL,NIL));
yuuji@0 317 puts (mail_fetchtext (stream,last));
yuuji@0 318 mail_free_stringlist (&lines);
yuuji@0 319 }
yuuji@0 320 else puts ("?Bad message number");
yuuji@0 321 break;
yuuji@0 322 case 'U': /* Undelete command */
yuuji@0 323 if (arg) last = atoi (arg);
yuuji@0 324 else {
yuuji@0 325 if (!last) {
yuuji@0 326 puts ("?Missing message number");
yuuji@0 327 break;
yuuji@0 328 }
yuuji@0 329 arg = cmd;
yuuji@0 330 sprintf (arg,"%lu",last);
yuuji@0 331 }
yuuji@0 332 if (last > 0 && last <= stream->nmsgs)
yuuji@0 333 mail_clearflag (stream,arg,"\\DELETED");
yuuji@0 334 else puts ("?Bad message number");
yuuji@0 335 break;
yuuji@0 336 case 'X': /* Xit command */
yuuji@0 337 mail_expunge (stream);
yuuji@0 338 mail_close (stream);
yuuji@0 339 stream = NIL;
yuuji@0 340 break;
yuuji@0 341 case '+':
yuuji@0 342 mail_debug (stream); debug = T;
yuuji@0 343 break;
yuuji@0 344 case '-':
yuuji@0 345 mail_nodebug (stream); debug = NIL;
yuuji@0 346 break;
yuuji@0 347 case '?': /* ? command */
yuuji@0 348 puts ("Body, Check, Delete, Expunge, Find, GC, Headers, Literal,");
yuuji@0 349 puts (" MailboxStatus, New Mailbox, Overview, Ping, Quit, Send, Type,");
yuuji@0 350 puts ("Undelete, Xit, +, -, or <RETURN> for next message");
yuuji@0 351 break;
yuuji@0 352 default: /* bogus command */
yuuji@0 353 printf ("?Unrecognized command: %s\n",cmd);
yuuji@0 354 break;
yuuji@0 355 }
yuuji@0 356 }
yuuji@0 357 }
yuuji@0 358
yuuji@0 359 /* MM display header
yuuji@0 360 * Accepts: IMAP2 stream
yuuji@0 361 * message number
yuuji@0 362 */
yuuji@0 363
yuuji@0 364 void overview_header (MAILSTREAM *stream,unsigned long uid,OVERVIEW *ov,
yuuji@0 365 unsigned long msgno)
yuuji@0 366 {
yuuji@0 367 if (ov) {
yuuji@0 368 unsigned long i;
yuuji@0 369 char *t,tmp[MAILTMPLEN];
yuuji@0 370 ADDRESS *adr;
yuuji@0 371 MESSAGECACHE *elt = mail_elt (stream,msgno);
yuuji@0 372 MESSAGECACHE selt;
yuuji@0 373 tmp[0] = elt->recent ? (elt->seen ? 'R': 'N') : ' ';
yuuji@0 374 tmp[1] = (elt->recent | elt->seen) ? ' ' : 'U';
yuuji@0 375 tmp[2] = elt->flagged ? 'F' : ' ';
yuuji@0 376 tmp[3] = elt->answered ? 'A' : ' ';
yuuji@0 377 tmp[4] = elt->deleted ? 'D' : ' ';
yuuji@0 378 mail_parse_date (&selt,ov->date);
yuuji@0 379 sprintf (tmp+5,"%4lu) ",elt->msgno);
yuuji@0 380 mail_date (tmp+11,&selt);
yuuji@0 381 tmp[17] = ' ';
yuuji@0 382 tmp[18] = '\0';
yuuji@0 383 memset (tmp+18,' ',(size_t) 20);
yuuji@0 384 tmp[38] = '\0'; /* tie off with null */
yuuji@0 385 /* get first from address from envelope */
yuuji@0 386 for (adr = ov->from; adr && !adr->host; adr = adr->next);
yuuji@0 387 if (adr) { /* if a personal name exists use it */
yuuji@0 388 if (!(t = adr->personal))
yuuji@0 389 sprintf (t = tmp+400,"%s@%s",adr->mailbox,adr->host);
yuuji@0 390 memcpy (tmp+18,t,(size_t) min (20,(long) strlen (t)));
yuuji@0 391 }
yuuji@0 392 strcat (tmp," ");
yuuji@0 393 if (i = elt->user_flags) {
yuuji@0 394 strcat (tmp,"{");
yuuji@0 395 while (i) {
yuuji@0 396 strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
yuuji@0 397 if (i) strcat (tmp," ");
yuuji@0 398 }
yuuji@0 399 strcat (tmp,"} ");
yuuji@0 400 }
yuuji@0 401 sprintf (tmp + strlen (tmp),"%.25s (%lu chars)",
yuuji@0 402 ov->subject ? ov->subject : " ",ov->optional.octets);
yuuji@0 403 puts (tmp);
yuuji@0 404 }
yuuji@0 405 else printf ("%%No overview for UID %lu\n",uid);
yuuji@0 406 }
yuuji@0 407
yuuji@0 408 /* MM display header
yuuji@0 409 * Accepts: IMAP2 stream
yuuji@0 410 * message number
yuuji@0 411 */
yuuji@0 412
yuuji@0 413 void header (MAILSTREAM *stream,long msgno)
yuuji@0 414 {
yuuji@0 415 unsigned long i;
yuuji@0 416 char tmp[MAILTMPLEN];
yuuji@0 417 char *t;
yuuji@0 418 MESSAGECACHE *cache = mail_elt (stream,msgno);
yuuji@0 419 mail_fetchstructure (stream,msgno,NIL);
yuuji@0 420 tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
yuuji@0 421 tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
yuuji@0 422 tmp[2] = cache->flagged ? 'F' : ' ';
yuuji@0 423 tmp[3] = cache->answered ? 'A' : ' ';
yuuji@0 424 tmp[4] = cache->deleted ? 'D' : ' ';
yuuji@0 425 sprintf (tmp+5,"%4lu) ",cache->msgno);
yuuji@0 426 mail_date (tmp+11,cache);
yuuji@0 427 tmp[17] = ' ';
yuuji@0 428 tmp[18] = '\0';
yuuji@0 429 mail_fetchfrom (tmp+18,stream,msgno,(long) 20);
yuuji@0 430 strcat (tmp," ");
yuuji@0 431 if (i = cache->user_flags) {
yuuji@0 432 strcat (tmp,"{");
yuuji@0 433 while (i) {
yuuji@0 434 strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
yuuji@0 435 if (i) strcat (tmp," ");
yuuji@0 436 }
yuuji@0 437 strcat (tmp,"} ");
yuuji@0 438 }
yuuji@0 439 mail_fetchsubject (t = tmp + strlen (tmp),stream,msgno,(long) 25);
yuuji@0 440 sprintf (t += strlen (t)," (%lu chars)",cache->rfc822_size);
yuuji@0 441 puts (tmp);
yuuji@0 442 }
yuuji@0 443
yuuji@0 444 /* MM display body
yuuji@0 445 * Accepts: BODY structure pointer
yuuji@0 446 * prefix string
yuuji@0 447 * index
yuuji@0 448 */
yuuji@0 449
yuuji@0 450 void display_body (BODY *body,char *pfx,long i)
yuuji@0 451 {
yuuji@0 452 char tmp[MAILTMPLEN];
yuuji@0 453 char *s = tmp;
yuuji@0 454 PARAMETER *par;
yuuji@0 455 PART *part; /* multipart doesn't have a row to itself */
yuuji@0 456 if (body->type == TYPEMULTIPART) {
yuuji@0 457 /* if not first time, extend prefix */
yuuji@0 458 if (pfx) sprintf (tmp,"%s%ld.",pfx,++i);
yuuji@0 459 else tmp[0] = '\0';
yuuji@0 460 for (i = 0,part = body->nested.part; part; part = part->next)
yuuji@0 461 display_body (&part->body,tmp,i++);
yuuji@0 462 }
yuuji@0 463 else { /* non-multipart, output oneline descriptor */
yuuji@0 464 if (!pfx) pfx = ""; /* dummy prefix if top level */
yuuji@0 465 sprintf (s," %s%ld %s",pfx,++i,body_types[body->type]);
yuuji@0 466 if (body->subtype) sprintf (s += strlen (s),"/%s",body->subtype);
yuuji@0 467 if (body->description) sprintf (s += strlen (s)," (%s)",body->description);
yuuji@0 468 if (par = body->parameter) do
yuuji@0 469 sprintf (s += strlen (s),";%s=%s",par->attribute,par->value);
yuuji@0 470 while (par = par->next);
yuuji@0 471 if (body->id) sprintf (s += strlen (s),", id = %s",body->id);
yuuji@0 472 switch (body->type) { /* bytes or lines depending upon body type */
yuuji@0 473 case TYPEMESSAGE: /* encapsulated message */
yuuji@0 474 case TYPETEXT: /* plain text */
yuuji@0 475 sprintf (s += strlen (s)," (%lu lines)",body->size.lines);
yuuji@0 476 break;
yuuji@0 477 default:
yuuji@0 478 sprintf (s += strlen (s)," (%lu bytes)",body->size.bytes);
yuuji@0 479 break;
yuuji@0 480 }
yuuji@0 481 puts (tmp); /* output this line */
yuuji@0 482 /* encapsulated message? */
yuuji@0 483 if ((body->type == TYPEMESSAGE) && !strcmp (body->subtype,"RFC822") &&
yuuji@0 484 (body = body->nested.msg->body)) {
yuuji@0 485 if (body->type == TYPEMULTIPART) display_body (body,pfx,i-1);
yuuji@0 486 else { /* build encapsulation prefix */
yuuji@0 487 sprintf (tmp,"%s%ld.",pfx,i);
yuuji@0 488 display_body (body,tmp,(long) 0);
yuuji@0 489 }
yuuji@0 490 }
yuuji@0 491 }
yuuji@0 492 }
yuuji@0 493
yuuji@0 494 /* MM status report
yuuji@0 495 * Accepts: MAIL stream
yuuji@0 496 */
yuuji@0 497
yuuji@0 498 void status (MAILSTREAM *stream)
yuuji@0 499 {
yuuji@0 500 unsigned long i;
yuuji@0 501 char *s,date[MAILTMPLEN];
yuuji@0 502 THREADER *thr;
yuuji@0 503 AUTHENTICATOR *auth;
yuuji@0 504 rfc822_date (date);
yuuji@0 505 puts (date);
yuuji@0 506 if (stream) {
yuuji@0 507 if (stream->mailbox)
yuuji@0 508 printf (" %s mailbox: %s, %lu messages, %lu recent\n",
yuuji@0 509 stream->dtb->name,stream->mailbox,stream->nmsgs,stream->recent);
yuuji@0 510 else puts ("%No mailbox is open on this stream");
yuuji@0 511 if (stream->user_flags[0]) {
yuuji@0 512 printf ("Keywords: %s",stream->user_flags[0]);
yuuji@0 513 for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
yuuji@0 514 printf (", %s",stream->user_flags[i]);
yuuji@0 515 puts ("");
yuuji@0 516 }
yuuji@0 517 if (!strcmp (stream->dtb->name,"imap")) {
yuuji@0 518 if (LEVELIMAP4rev1 (stream)) s = "IMAP4rev1 (RFC 3501)";
yuuji@0 519 else if (LEVEL1730 (stream)) s = "IMAP4 (RFC 1730)";
yuuji@0 520 else if (LEVELIMAP2bis (stream)) s = "IMAP2bis";
yuuji@0 521 else if (LEVEL1176 (stream)) s = "IMAP2 (RFC 1176)";
yuuji@0 522 else s = "IMAP2 (RFC 1064)";
yuuji@0 523 printf ("%s server %s\n",s,imap_host (stream));
yuuji@0 524 if (LEVELIMAP4 (stream)) {
yuuji@0 525 if (i = imap_cap (stream)->auth) {
yuuji@0 526 s = "";
yuuji@0 527 printf ("Mutually-supported SASL mechanisms:");
yuuji@0 528 while (auth = mail_lookup_auth (find_rightmost_bit (&i) + 1)) {
yuuji@0 529 printf (" %s",auth->name);
yuuji@0 530 if (!strcmp (auth->name,"PLAIN"))
yuuji@0 531 s = "\n [LOGIN will not be listed here if PLAIN is supported]";
yuuji@0 532 }
yuuji@0 533 puts (s);
yuuji@0 534 }
yuuji@0 535 printf ("Supported standard extensions:\n");
yuuji@0 536 if (LEVELACL (stream)) puts (" Access Control lists (RFC 2086)");
yuuji@0 537 if (LEVELQUOTA (stream)) puts (" Quotas (RFC 2087)");
yuuji@0 538 if (LEVELLITERALPLUS (stream))
yuuji@0 539 puts (" Non-synchronizing literals (RFC 2088)");
yuuji@0 540 if (LEVELIDLE (stream)) puts (" IDLE unsolicited update (RFC 2177)");
yuuji@0 541 if (LEVELMBX_REF (stream)) puts (" Mailbox referrals (RFC 2193)");
yuuji@0 542 if (LEVELLOG_REF (stream)) puts (" Login referrals (RFC 2221)");
yuuji@0 543 if (LEVELANONYMOUS (stream)) puts (" Anonymous access (RFC 2245)");
yuuji@0 544 if (LEVELNAMESPACE (stream)) puts (" Multiple namespaces (RFC 2342)");
yuuji@0 545 if (LEVELUIDPLUS (stream)) puts (" Extended UID behavior (RFC 2359)");
yuuji@0 546 if (LEVELSTARTTLS (stream))
yuuji@0 547 puts (" Transport Layer Security (RFC 2595)");
yuuji@0 548 if (LEVELLOGINDISABLED (stream))
yuuji@0 549 puts (" LOGIN command disabled (RFC 2595)");
yuuji@0 550 if (LEVELID (stream))
yuuji@0 551 puts (" Implementation identity negotiation (RFC 2971)");
yuuji@0 552 if (LEVELCHILDREN (stream))
yuuji@0 553 puts (" LIST children announcement (RFC 3348)");
yuuji@0 554 if (LEVELMULTIAPPEND (stream))
yuuji@0 555 puts (" Atomic multiple APPEND (RFC 3502)");
yuuji@0 556 if (LEVELBINARY (stream))
yuuji@0 557 puts (" Binary body content (RFC 3516)");
yuuji@0 558 if (LEVELUNSELECT (stream)) puts (" Mailbox unselect (RFC 3691)");
yuuji@0 559 if (LEVELURLAUTH (stream))
yuuji@0 560 puts (" URL authenticated fetch (RFC 4467)");
yuuji@0 561 if (LEVELCATENATE (stream)) puts (" Catenation (RFC 4469)");
yuuji@0 562 if (LEVELCONDSTORE (stream)) puts (" Conditional STORE (RFC 4551)");
yuuji@0 563 if (LEVELESEARCH (stream)) puts (" Extended SEARCH (RFC 4731)");
yuuji@0 564 puts ("Supported draft extensions:");
yuuji@0 565 if (LEVELSASLIR (stream)) puts (" SASL initial client response");
yuuji@0 566 if (LEVELSORT (stream)) puts (" Server-based sorting");
yuuji@0 567 if (LEVELTHREAD (stream)) {
yuuji@0 568 printf (" Server-based threading:");
yuuji@0 569 for (thr = imap_cap (stream)->threader; thr; thr = thr->next)
yuuji@0 570 printf (" %s",thr->name);
yuuji@0 571 putchar ('\n');
yuuji@0 572 }
yuuji@0 573 if (LEVELSCAN (stream)) puts (" Mailbox text scan");
yuuji@0 574 if (i = imap_cap (stream)->extlevel) {
yuuji@0 575 printf ("Supported BODYSTRUCTURE extensions:");
yuuji@0 576 switch (i) {
yuuji@0 577 case BODYEXTLOC: printf (" location");
yuuji@0 578 case BODYEXTLANG: printf (" language");
yuuji@0 579 case BODYEXTDSP: printf (" disposition");
yuuji@0 580 case BODYEXTMD5: printf (" MD5\n");
yuuji@0 581 }
yuuji@0 582 }
yuuji@0 583 }
yuuji@0 584 else putchar ('\n');
yuuji@0 585 }
yuuji@0 586 }
yuuji@0 587 }
yuuji@0 588
yuuji@0 589
yuuji@0 590 /* Prompt user for input
yuuji@0 591 * Accepts: pointer to prompt message
yuuji@0 592 * pointer to input buffer
yuuji@0 593 */
yuuji@0 594
yuuji@0 595 void prompt (char *msg,char *txt)
yuuji@0 596 {
yuuji@0 597 printf ("%s",msg);
yuuji@0 598 gets (txt);
yuuji@0 599 }
yuuji@0 600
yuuji@0 601 /* Interfaces to C-client */
yuuji@0 602
yuuji@0 603
yuuji@0 604 void mm_searched (MAILSTREAM *stream,unsigned long number)
yuuji@0 605 {
yuuji@0 606 }
yuuji@0 607
yuuji@0 608
yuuji@0 609 void mm_exists (MAILSTREAM *stream,unsigned long number)
yuuji@0 610 {
yuuji@0 611 }
yuuji@0 612
yuuji@0 613
yuuji@0 614 void mm_expunged (MAILSTREAM *stream,unsigned long number)
yuuji@0 615 {
yuuji@0 616 }
yuuji@0 617
yuuji@0 618
yuuji@0 619 void mm_flags (MAILSTREAM *stream,unsigned long number)
yuuji@0 620 {
yuuji@0 621 }
yuuji@0 622
yuuji@0 623
yuuji@0 624 void mm_notify (MAILSTREAM *stream,char *string,long errflg)
yuuji@0 625 {
yuuji@0 626 mm_log (string,errflg);
yuuji@0 627 }
yuuji@0 628
yuuji@0 629
yuuji@0 630 void mm_list (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
yuuji@0 631 {
yuuji@0 632 putchar (' ');
yuuji@0 633 if (delimiter) putchar (delimiter);
yuuji@0 634 else fputs ("NIL",stdout);
yuuji@0 635 putchar (' ');
yuuji@0 636 fputs (mailbox,stdout);
yuuji@0 637 if (attributes & LATT_NOINFERIORS) fputs (", no inferiors",stdout);
yuuji@0 638 if (attributes & LATT_NOSELECT) fputs (", no select",stdout);
yuuji@0 639 if (attributes & LATT_MARKED) fputs (", marked",stdout);
yuuji@0 640 if (attributes & LATT_UNMARKED) fputs (", unmarked",stdout);
yuuji@0 641 putchar ('\n');
yuuji@0 642 }
yuuji@0 643
yuuji@0 644
yuuji@0 645 void mm_lsub (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
yuuji@0 646 {
yuuji@0 647 putchar (' ');
yuuji@0 648 if (delimiter) putchar (delimiter);
yuuji@0 649 else fputs ("NIL",stdout);
yuuji@0 650 putchar (' ');
yuuji@0 651 fputs (mailbox,stdout);
yuuji@0 652 if (attributes & LATT_NOINFERIORS) fputs (", no inferiors",stdout);
yuuji@0 653 if (attributes & LATT_NOSELECT) fputs (", no select",stdout);
yuuji@0 654 if (attributes & LATT_MARKED) fputs (", marked",stdout);
yuuji@0 655 if (attributes & LATT_UNMARKED) fputs (", unmarked",stdout);
yuuji@0 656 putchar ('\n');
yuuji@0 657 }
yuuji@0 658
yuuji@0 659
yuuji@0 660 void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
yuuji@0 661 {
yuuji@0 662 printf (" Mailbox %s",mailbox);
yuuji@0 663 if (status->flags & SA_MESSAGES) printf (", %lu messages",status->messages);
yuuji@0 664 if (status->flags & SA_RECENT) printf (", %lu recent",status->recent);
yuuji@0 665 if (status->flags & SA_UNSEEN) printf (", %lu unseen",status->unseen);
yuuji@0 666 if (status->flags & SA_UIDVALIDITY) printf (", %lu UID validity",
yuuji@0 667 status->uidvalidity);
yuuji@0 668 if (status->flags & SA_UIDNEXT) printf (", %lu next UID",status->uidnext);
yuuji@0 669 printf ("\n");
yuuji@0 670 }
yuuji@0 671
yuuji@0 672
yuuji@0 673 void mm_log (char *string,long errflg)
yuuji@0 674 {
yuuji@0 675 switch ((short) errflg) {
yuuji@0 676 case NIL:
yuuji@0 677 printf ("[%s]\n",string);
yuuji@0 678 break;
yuuji@0 679 case PARSE:
yuuji@0 680 case WARN:
yuuji@0 681 printf ("%%%s\n",string);
yuuji@0 682 break;
yuuji@0 683 case ERROR:
yuuji@0 684 printf ("?%s\n",string);
yuuji@0 685 break;
yuuji@0 686 }
yuuji@0 687 }
yuuji@0 688
yuuji@0 689
yuuji@0 690 void mm_dlog (char *string)
yuuji@0 691 {
yuuji@0 692 puts (string);
yuuji@0 693 }
yuuji@0 694
yuuji@0 695
yuuji@0 696 void mm_login (NETMBX *mb,char *user,char *pwd,long trial)
yuuji@0 697 {
yuuji@0 698 char *s,tmp[MAILTMPLEN];
yuuji@0 699 if (curhst) fs_give ((void **) &curhst);
yuuji@0 700 curhst = (char *) fs_get (1+strlen (mb->host));
yuuji@0 701 strcpy (curhst,mb->host);
yuuji@0 702 sprintf (s = tmp,"{%s/%s",mb->host,mb->service);
yuuji@0 703 if (*mb->user) sprintf (tmp+strlen (tmp),"/user=%s",strcpy (user,mb->user));
yuuji@0 704 if (*mb->authuser) sprintf (tmp+strlen (tmp),"/authuser=%s",mb->authuser);
yuuji@0 705 if (*mb->user) strcat (s = tmp,"} password:");
yuuji@0 706 else {
yuuji@0 707 printf ("%s} username: ",tmp);
yuuji@0 708 fgets (user,NETMAXUSER-1,stdin);
yuuji@0 709 user[NETMAXUSER-1] = '\0';
yuuji@0 710 if (s = strchr (user,'\n')) *s = '\0';
yuuji@0 711 s = "password: ";
yuuji@0 712 }
yuuji@0 713 if (curusr) fs_give ((void **) &curusr);
yuuji@0 714 curusr = cpystr (user);
yuuji@0 715 strcpy (pwd,getpass (s));
yuuji@0 716 }
yuuji@0 717
yuuji@0 718
yuuji@0 719 void mm_critical (MAILSTREAM *stream)
yuuji@0 720 {
yuuji@0 721 }
yuuji@0 722
yuuji@0 723
yuuji@0 724 void mm_nocritical (MAILSTREAM *stream)
yuuji@0 725 {
yuuji@0 726 }
yuuji@0 727
yuuji@0 728
yuuji@0 729 long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
yuuji@0 730 {
yuuji@0 731 #if UNIXLIKE
yuuji@0 732 kill (getpid (),SIGSTOP);
yuuji@0 733 #else
yuuji@0 734 abort ();
yuuji@0 735 #endif
yuuji@0 736 return NIL;
yuuji@0 737 }
yuuji@0 738
yuuji@0 739
yuuji@0 740 void mm_fatal (char *string)
yuuji@0 741 {
yuuji@0 742 printf ("?%s\n",string);
yuuji@0 743 }
yuuji@0 744
yuuji@0 745 /* SMTP tester */
yuuji@0 746
yuuji@0 747 void smtptest (long debug)
yuuji@0 748 {
yuuji@0 749 SENDSTREAM *stream = NIL;
yuuji@0 750 char line[MAILTMPLEN];
yuuji@0 751 char *text = (char *) fs_get (8*MAILTMPLEN);
yuuji@0 752 ENVELOPE *msg = mail_newenvelope ();
yuuji@0 753 BODY *body = mail_newbody ();
yuuji@0 754 msg->from = mail_newaddr ();
yuuji@0 755 msg->from->personal = cpystr (personalname);
yuuji@0 756 msg->from->mailbox = cpystr (curusr);
yuuji@0 757 msg->from->host = cpystr (curhst);
yuuji@0 758 msg->return_path = mail_newaddr ();
yuuji@0 759 msg->return_path->mailbox = cpystr (curusr);
yuuji@0 760 msg->return_path->host = cpystr (curhst);
yuuji@0 761 prompt ("To: ",line);
yuuji@0 762 rfc822_parse_adrlist (&msg->to,line,curhst);
yuuji@0 763 if (msg->to) {
yuuji@0 764 prompt ("cc: ",line);
yuuji@0 765 rfc822_parse_adrlist (&msg->cc,line,curhst);
yuuji@0 766 }
yuuji@0 767 else {
yuuji@0 768 prompt ("Newsgroups: ",line);
yuuji@0 769 if (*line) msg->newsgroups = cpystr (line);
yuuji@0 770 else {
yuuji@0 771 mail_free_body (&body);
yuuji@0 772 mail_free_envelope (&msg);
yuuji@0 773 fs_give ((void **) &text);
yuuji@0 774 return;
yuuji@0 775 }
yuuji@0 776 }
yuuji@0 777 prompt ("Subject: ",line);
yuuji@0 778 msg->subject = cpystr (line);
yuuji@0 779 puts (" Msg (end with a line with only a '.'):");
yuuji@0 780 body->type = TYPETEXT;
yuuji@0 781 *text = '\0';
yuuji@0 782 while (gets (line)) {
yuuji@0 783 if (line[0] == '.') {
yuuji@0 784 if (line[1] == '\0') break;
yuuji@0 785 else strcat (text,".");
yuuji@0 786 }
yuuji@0 787 strcat (text,line);
yuuji@0 788 strcat (text,"\015\012");
yuuji@0 789 }
yuuji@0 790 body->contents.text.data = (unsigned char *) text;
yuuji@0 791 body->contents.text.size = strlen (text);
yuuji@0 792 rfc822_date (line);
yuuji@0 793 msg->date = (char *) fs_get (1+strlen (line));
yuuji@0 794 strcpy (msg->date,line);
yuuji@0 795 if (msg->to) {
yuuji@0 796 puts ("Sending...");
yuuji@0 797 if (stream = smtp_open (hostlist,debug)) {
yuuji@0 798 if (smtp_mail (stream,"MAIL",msg,body)) puts ("[Ok]");
yuuji@0 799 else printf ("[Failed - %s]\n",stream->reply);
yuuji@0 800 }
yuuji@0 801 }
yuuji@0 802 else {
yuuji@0 803 puts ("Posting...");
yuuji@0 804 if (stream = nntp_open (newslist,debug)) {
yuuji@0 805 if (nntp_mail (stream,msg,body)) puts ("[Ok]");
yuuji@0 806 else printf ("[Failed - %s]\n",stream->reply);
yuuji@0 807 }
yuuji@0 808 }
yuuji@0 809 if (stream) smtp_close (stream);
yuuji@0 810 else puts ("[Can't open connection to any server]");
yuuji@0 811 mail_free_envelope (&msg);
yuuji@0 812 mail_free_body (&body);
yuuji@0 813 }

UW-IMAP'd extensions by yuuji