summaryrefslogtreecommitdiff
path: root/imap/src/mailutil
diff options
context:
space:
mode:
Diffstat (limited to 'imap/src/mailutil')
-rw-r--r--imap/src/mailutil/Makefile51
-rw-r--r--imap/src/mailutil/mailutil.1264
-rw-r--r--imap/src/mailutil/mailutil.c942
-rw-r--r--imap/src/mailutil/makefile.nt50
-rw-r--r--imap/src/mailutil/makefile.ntk51
-rw-r--r--imap/src/mailutil/makefile.w2k49
6 files changed, 1407 insertions, 0 deletions
diff --git a/imap/src/mailutil/Makefile b/imap/src/mailutil/Makefile
new file mode 100644
index 00000000..acc58bbd
--- /dev/null
+++ b/imap/src/mailutil/Makefile
@@ -0,0 +1,51 @@
+# ========================================================================
+# 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
+#
+#
+# ========================================================================
+
+
+# Program: mailutil Makefile
+#
+# Author: Mark Crispin
+# Networks and Distributed Computing
+# Computing & Communications
+# University of Washington
+# Administration Building, AG-44
+# Seattle, WA 98195
+# Internet: MRC@CAC.Washington.EDU
+#
+# Date: 2 February 1993
+# Last Edited: 30 August 2006
+
+
+C = ../c-client
+CCLIENTLIB = $C/c-client.a
+SHELL = /bin/sh
+
+# Get local definitions from c-client directory
+
+CC = `cat $C/CCTYPE`
+CFLAGS = -I$C `cat $C/CFLAGS`
+LDFLAGS = $(CCLIENTLIB) `cat $C/LDFLAGS`
+
+mailutil: $(CCLIENTLIB) mailutil.o
+ $(CC) $(CFLAGS) -o mailutil mailutil.o $(LDFLAGS)
+
+mailutil.o: $C/mail.h $C/misc.h $C/osdep.h
+
+$(CCLIENTLIB):
+ cd $C;make
+
+clean:
+ rm -f *.o mailutil
+
+# A monument to a hack of long ago and far away...
+love:
+ @echo 'not war?'
diff --git a/imap/src/mailutil/mailutil.1 b/imap/src/mailutil/mailutil.1
new file mode 100644
index 00000000..964fb1b8
--- /dev/null
+++ b/imap/src/mailutil/mailutil.1
@@ -0,0 +1,264 @@
+.ig
+ * ========================================================================
+ * Copyright 1988-2008 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
+ *
+ *
+ * ========================================================================
+..
+.TH mailutil 1 "March 3, 2008"
+.SH NAME
+mailutil - mail utility program
+.nh
+.SH SYNTAX
+.B mailutil command [switches] [arguments]
+.PP
+All commands accept the -d, -v, and -u switches in addition to any
+command-specific switches.
+.PP
+.B mailutil check [MAILBOX]
+.PP
+.B mailutil create MAILBOX
+.PP
+.B mailutil delete MAILBOX
+.PP
+.B mailutil rename SOURCE DESTINATION
+.PP
+.B mailutil copy [-rw] [-kw] [-ig] SOURCE DESTINATION
+.PP
+.B mailutil move [-rw] [-kw] [-ig] SOURCE DESTINATION
+.PP
+.B mailutil append [-rw] [-kw] [-ig] SOURCE DESTINATION
+.PP
+.B mailutil appenddelete [-rw] [-kw] [-ig] SOURCE DESTINATION
+.PP
+.B mailutil prune MAILBOX CRITERIA
+.PP
+.B mailutil transfer [-m mode] [-rw] [-kw] [-ig] SOURCE DESTINATION
+.SH DESCRIPTION
+.B mailutil
+replaces the old chkmail, imapcopy, imapmove, imapxfer, mbxcopy,
+mbxcreat, and mbxcvt programs.
+.PP
+.B mailutil check
+determines whether new mail exists in the given mailbox (the default
+is INBOX). The number of new messages is defined as the number of
+messages that have "Recent" status set. If the mailbox contains no
+new messages,
+.B mailutil check
+will indicate that no new mail is present;
+otherwise, it will report the number of new messages. In either case,
+it will also indicate the canonical form of the name of the mailbox.
+.PP
+.B mailutil create
+creates a new
+.I mailbox
+with the given name. The mailbox name must not already exist. A mailbox
+can be created in a particular format by prefixing the name with
+.I #driver.
+followed by the format name and a
+.I /
+character. For example, the command
+.br
+ mailutil create #driver.mbx/junkmail
+.br
+will create a new mailbox named "junkmail" in mbx format.
+.PP
+.B mailutil delete
+deletes an existing
+.I mailbox
+with the given name.
+.PP
+.B mailutil rename
+renames an existing mailbox to a new name (which must not already exist).
+This only works if the old and new names are in the same mail store. A
+more general means to rename a mailbox is to do a
+.B mailutil copy
+of the old name to the new name, followed by a
+.B mailutil delete
+of the old name.
+.PP
+.B mailutil copy
+creates a new mailbox and copies messages from the old mailbox to the
+new mailbox. As in
+.B mailutil create
+a mailbox format can be specified with the new mailbox. For example, the
+command
+.br
+ mailutil copy INBOX #driver.mbx/INBOX
+.br
+will copy messages from your existing INBOX to an mbx-format INBOX.
+.PP
+.B mailutil move
+is similar to
+.B mailutil copy
+but in addition will also remove (delete and expunge) the messages from the
+old mailbox after copying them to the new mailbox.
+.PP
+.B mailutil append
+and
+.B mailutil appenddelete
+are similar to
+.B mailutil copy
+and
+.B mailutil move
+respectively except that they do not create the destination mailbox.
+.PP
+.B mailutil prune
+prunes the mailbox of messages which match certain criteria, which are
+in the form of IMAP2 (RFC 1176) SEARCH arguments. For example, the
+command.
+.br
+ mailutil prune INBOX "before 1-jan-2004"
+.br
+will delete and expunge all messages written before January 1, 2004.
+.PP
+Note that mailutil implements pruning by deleting the matching messages,
+and then expunging the mailbox. Consequently, mailutil will also expunge
+any messages which were deleted at the time of the pruning.
+.PP
+.B mailutil transfer
+copies an entire hierarchy of mailboxes from the named source to the
+named destination. Mailboxes are created on the destination as
+needed. Any error in copying messages will cause the transfer to stop.
+.PP
+Normally, any error in creation will cause the transfer to stop.
+However, if
+.B -m MODE
+or
+.B -merge MODE
+is specified, a merging transfer is performed. The
+.B MODE
+argument indicats the type of merge:
+.PP
+.B -m[erge] prompt
+indicates that the user should be asked for an alternative name to create.
+If creating the new name fails, the user will be asked again.
+.PP
+.B -m[erge] append
+indicates that it's alright to copy the messages into an existing mailbox
+with that name. If the mailbox does not exist, the user will be prompted
+for an alternative name.
+.PP
+.B -m[erge] suffix=XXXX
+where XXXX is any string, indicates that an alternative name should be
+built by appending the given suffix to the name. It that alternative name
+can't be created, then the user will be prompted for an alternative name.
+.PP
+The source hierarchy consists of all mailboxes which start
+with the given source name. With the exception of a remote system
+specification (within "{}" braces), the source name is used as the
+name of the destination. The destination hierarchy is a prefix
+applied to any new names being created. For example,
+.br
+ mailutil transfer foo bar
+.br
+will copy all mailboxes with names beginning with "foo" to names
+beginning with "bar" (hence "foobar" will be copied to "barfoobar").
+Similarly,
+.br
+ mailutil transfer "{imap.foo.com}" "{imap.bar.com}old/"
+.br
+will copy all mailboxes from the imap.foo.com IMAP server to
+equivalent names starting with "old/" on the imap.bar.com IMAP server.
+.SH FLAGS
+The
+.B -d
+or
+.B -debug
+flag prints full debugging telemetry including protocol operations.
+.PP
+The
+.B -v
+or
+.B -verbose
+flag prints verbose (non-error) telemetry.
+.PP
+The
+.B -u USERID
+or
+.B -user USERID
+switch attempts to become the indicated user. This is for the benefit of
+system administrators who want to do mailutil operations on a userid that
+does not normally have shell access.
+.PP
+The
+.B -rw
+or
+.B -rwcopy
+flag causes the source mailbox to be open in readwrite mode rather than
+readonly mode. Normally, mailutil tries to use readonly mode to avoid
+altering any flags in the source mailbox, but some mailbox types, e.g.
+POP3, can't be open in readonly mode.
+.PP
+The
+.B -kw
+or
+.B -kwcopy
+flag causes the keywords of the source mailbox to be created in the
+destination mailbox. Normally, mailutil does not create keywords in
+the destination mailbox so only those keywords that are already defined
+in the destination mailbox will be preserved. Note that some IMAP servers
+may automatically create keywords, so this flag may not be necessary.
+.PP
+The
+.B -ig
+or
+.B -ignore
+flag causes the keywords of the source mailbox to be ignored completely
+and no attempt is made to copy them to the destination mailbox.
+.PP
+The
+.B -ig[nore]
+and
+.B -kw[copy]
+flags are mutually exclusive.
+.SH ARGUMENTS
+The arguments are standard c-client mailbox names. A
+variety of mailbox name formats and types of mailboxes are supported
+by c-client; examples of the most common forms of names are:
+.PP
+.I
+.IP Name 15
+.I Meaning
+.IP INBOX
+primary incoming mail folder on the local system
+.IP archive/tx-project
+mail folder named "tx-project" in "archive" subdirectory of local
+filesystem home directory
+.IP {imapserver.foo.com}INBOX
+primary incoming mail folder on IMAP server system
+"imapserver.foo.com"
+.IP {imapserver.foo.com}archive/tx-project
+mail folder named "tx-project" in "archive" subdirectory on IMAP
+server system "imapserver.foo.com"
+.IP #news.comp.mail.misc
+newsgroup "comp.mail.misc" on local filesystem
+.IP {newserver.foo.com/nntp}comp.mail.misc
+newsgroup "comp.mail.misc" on NNTP server system "newserver.foo.com"
+.IP {popserver.foo.com/pop3}
+mail folder on POP3 server system "popserver.foo.com"
+.LP
+See your system manager for more information about the types of
+mailboxes which are available on your system.
+.SH RESTRICTIONS
+You must surround a
+.I {host}mailbox
+argument with quotation marks if you run
+.B mailutil
+from
+.IR csh (1)
+or another shell for which braces have special meaning.
+.PP
+You must surround a
+.I #driver.format/mailbox
+argument with quotation marks if you run
+.B mailutil
+from a shell in which "#" is the comment character.
+.SH AUTHOR
+Mark Crispin, MRC@Washington.EDU
diff --git a/imap/src/mailutil/mailutil.c b/imap/src/mailutil/mailutil.c
new file mode 100644
index 00000000..2489195f
--- /dev/null
+++ b/imap/src/mailutil/mailutil.c
@@ -0,0 +1,942 @@
+/* ========================================================================
+ * Copyright 1988-2008 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
+ *
+ *
+ * ========================================================================
+ */
+
+/*
+ * Program: Mail utility
+ *
+ * Author: Mark Crispin
+ * UW Technology
+ * University of Washington
+ * Seattle, WA 98195
+ * Internet: MRC@Washington.EDU
+ *
+ * Date: 2 February 1994
+ * Last Edited: 19 February 2008
+ */
+
+
+#include <stdio.h>
+#include <errno.h>
+extern int errno; /* just in case */
+#include "c-client.h"
+#ifdef SYSCONFIG /* defined in env_unix.h */
+#include <pwd.h>
+#endif
+
+/* Globals */
+
+char *version = "13"; /* edit number */
+int debugp = NIL; /* flag saying debug */
+int verbosep = NIL; /* flag saying verbose */
+int rwcopyp = NIL; /* flag saying readwrite copy (for POP) */
+int kwcopyp = NIL; /* flag saying keyword copy */
+int ignorep = NIL; /* flag saying ignore keywords */
+int critical = NIL; /* flag saying in critical code */
+int trycreate = NIL; /* [TRYCREATE] seen */
+char *suffix = NIL; /* suffer merge mode suffix text */
+int ddelim = -1; /* destination delimiter */
+FILE *f = NIL;
+
+/* Usage strings */
+
+char *usage2 = "usage: %s %s\n\n%s\n";
+char *usage3 = "usage: %s %s %s\n\n%s\n";
+char *usgchk = "check [MAILBOX]";
+char *usgcre = "create MAILBOX";
+char *usgdel = "delete MAILBOX";
+char *usgren = "rename SOURCE DESTINATION";
+char *usgcpymov = "[-rw[copy]] [-kw[copy]] [-ig[nore]] SOURCE DESTINATION";
+char *usgappdel = "[-rw[copy]] [-kw[copy]] [-ig[nore]] SOURCE DESTINATION";
+char *usgprn = "prune mailbox SEARCH_CRITERIA";
+char *usgxfr = "transfer [-rw[copy]] [-kw[copy]] [-ig[nore]] [-m[erge] m] SOURCE DEST";
+#ifdef SYSCONFIG
+char *stdsw = "Standard switches valid with any command:\n\t[-d[ebug]] [-v[erbose]] [-u[ser] userid] [--]";
+#else
+char *stdsw = "Standard switches valid with any command:\n\t[-d[ebug]] [-v[erbose]]";
+#endif
+
+/* Merge modes */
+
+#define mPROMPT 1
+#define mAPPEND 2
+#define mSUFFIX 3
+
+
+/* Function prototypes */
+
+void ms_init (STRING *s,void *data,unsigned long size);
+char ms_next (STRING *s);
+void ms_setpos (STRING *s,unsigned long i);
+int main (int argc,char *argv[]);
+SEARCHPGM *prune_criteria (char *criteria);
+int prune_criteria_number (unsigned long *number,char **r);
+int mbxcopy (MAILSTREAM *source,MAILSTREAM *dest,char *dst,int create,int del,
+ int mode);
+long mm_append (MAILSTREAM *stream,void *data,char **flags,char **date,
+ STRING **message);
+
+
+/* Append package */
+
+typedef struct append_package {
+ MAILSTREAM *stream; /* source stream */
+ unsigned long msgno; /* current message number */
+ unsigned long msgmax; /* maximum message number */
+ char *flags; /* current flags */
+ char *date; /* message internal date */
+ STRING *message; /* stringstruct of message */
+} APPENDPACKAGE;
+
+
+/* Message string driver for message stringstructs */
+
+STRINGDRIVER mstring = {
+ ms_init, /* initialize string structure */
+ ms_next, /* get next byte in string structure */
+ ms_setpos /* set position in string structure */
+};
+
+/* Initialize file string structure for file stringstruct
+ * Accepts: string structure
+ * pointer to message data structure
+ * size of string
+ */
+
+void ms_init (STRING *s,void *data,unsigned long size)
+{
+ APPENDPACKAGE *md = (APPENDPACKAGE *) data;
+ s->data = data; /* note stream/msgno and header length */
+ mail_fetch_header (md->stream,md->msgno,NIL,NIL,&s->data1,
+ FT_PREFETCHTEXT|FT_PEEK);
+#if 0
+ s->size = size; /* message size */
+#else /* This kludge is necessary because of broken IMAP servers (sigh!) */
+ mail_fetch_text (md->stream,md->msgno,NIL,&s->size,FT_PEEK);
+ s->size += s->data1; /* header + body size */
+#endif
+ SETPOS (s,0);
+}
+
+
+/* Get next character from file stringstruct
+ * Accepts: string structure
+ * Returns: character, string structure chunk refreshed
+ */
+
+char ms_next (STRING *s)
+{
+ char c = *s->curpos++; /* get next byte */
+ SETPOS (s,GETPOS (s)); /* move to next chunk */
+ return c; /* return the byte */
+}
+
+
+/* Set string pointer position for file stringstruct
+ * Accepts: string structure
+ * new position
+ */
+
+void ms_setpos (STRING *s,unsigned long i)
+{
+ APPENDPACKAGE *md = (APPENDPACKAGE *) s->data;
+ if (i < s->data1) { /* want header? */
+ s->chunk = mail_fetch_header (md->stream,md->msgno,NIL,NIL,NIL,FT_PEEK);
+ s->chunksize = s->data1; /* header length */
+ s->offset = 0; /* offset is start of message */
+ }
+ else if (i < s->size) { /* want body */
+ s->chunk = mail_fetch_text (md->stream,md->msgno,NIL,NIL,FT_PEEK);
+ s->chunksize = s->size - s->data1;
+ s->offset = s->data1; /* offset is end of header */
+ }
+ else { /* off end of message */
+ s->chunk = NIL; /* make sure that we crack on this then */
+ s->chunksize = 1; /* make sure SNX cracks the right way... */
+ s->offset = i;
+ }
+ /* initial position and size */
+ s->curpos = s->chunk + (i -= s->offset);
+ s->cursize = s->chunksize - i;
+}
+
+/* Main program */
+
+int main (int argc,char *argv[])
+{
+ MAILSTREAM *source = NIL;
+ MAILSTREAM *dest = NIL;
+ SEARCHPGM *criteria;
+ char c,*s,*dp,*t,*t1,tmp[MAILTMPLEN],mbx[MAILTMPLEN];
+ unsigned long m,len,curlen,start,last;
+ int i;
+ int merge = NIL;
+ int retcode = 1;
+ int moreswitchp = T;
+ char *cmd = NIL;
+ char *src = NIL;
+ char *dst = NIL;
+ char *pgm = argc ? argv[0] : "mailutil";
+#include "linkage.c"
+ for (i = 1; i < argc; i++) {
+ s = argv[i]; /* pick up argument */
+ /* parse switches */
+ if (moreswitchp && (*s == '-')) {
+ if (!strcmp (s,"-debug") || !strcmp (s,"-d")) debugp = T;
+ else if (!strcmp (s,"-verbose") || !strcmp (s,"-v")) verbosep = T;
+ else if (!strcmp (s,"-rwcopy") || !strcmp (s,"-rw")) rwcopyp = T;
+ else if (!strcmp (s,"-kwcopy") || !strcmp (s,"-kw")) kwcopyp = T;
+ else if (!strcmp (s,"-ignore") || !strcmp (s,"-ig")) ignorep = T;
+ else if ((!strcmp (s,"-merge") || !strcmp (s,"-m")) && (++i < argc)) {
+ if (!strcmp (s = argv[i],"prompt")) merge = mPROMPT;
+ else if (!strcmp (s,"append")) merge = mAPPEND;
+ else if (!strncmp (s,"suffix=",7) && s[7]) {
+ merge = mSUFFIX;
+ suffix = cpystr (s+7);
+ }
+ else {
+ printf ("unknown merge option: %s\n",s);
+ exit (retcode);
+ }
+ }
+
+#ifdef SYSCONFIG
+ else if ((!strcmp (s,"-user") || !strcmp (s,"-u")) && (++i < argc)) {
+ struct passwd *pw = getpwnam (s = argv[i]);
+ if (!pw) {
+ printf ("unknown user id: %s\n",argv[i]);
+ exit (retcode);
+ }
+ else if (setuid (pw->pw_uid)) {
+ perror ("unable to change user id");
+ exit (retcode);
+ }
+ }
+#endif
+ /* -- means no more switches, so mailbox
+ name can start with "-" */
+ else if ((s[1] == '-') && !s[2]) moreswitchp = NIL;
+ else {
+ printf ("unknown switch: %s\n",s);
+ exit (retcode);
+ }
+ }
+ else if (!cmd) cmd = s; /* first non-switch is command */
+ else if (!src) src = s; /* second non-switch is source */
+ else if (!dst) dst = s; /* third non-switch is destination */
+ else {
+ printf ("unknown argument: %s\n",s);
+ exit (retcode);
+ }
+ }
+ if (kwcopyp && ignorep) {
+ puts ("-kwcopy and -ignore are mutually exclusive");
+ exit (retcode);
+ }
+ if (!cmd) cmd = ""; /* prevent SEGV */
+
+ if (!strcmp (cmd,"check")) { /* check for new messages */
+ if (!src) src = "INBOX";
+ if (dst || merge || rwcopyp || kwcopyp || ignorep)
+ printf (usage2,pgm,usgchk,stdsw);
+ else if (mail_status (source = (*src == '{') ?
+ mail_open (NIL,src,OP_HALFOPEN |
+ (debugp ? OP_DEBUG : NIL)) : NIL,
+ src,SA_MESSAGES | SA_RECENT | SA_UNSEEN))
+ retcode = 0;
+ }
+ else if (!strcmp (cmd,"create")) {
+ if (!src || dst || merge || rwcopyp || kwcopyp || ignorep)
+ printf (usage2,pgm,usgcre,stdsw);
+ else if (mail_create (source = (*src == '{') ?
+ mail_open (NIL,src,OP_HALFOPEN |
+ (debugp ? OP_DEBUG : NIL)) : NIL,src))
+ retcode = 0;
+ }
+ else if (!strcmp (cmd,"delete")) {
+ if (!src || dst || merge || rwcopyp || kwcopyp || ignorep)
+ printf (usage2,pgm,usgdel,stdsw);
+ else if (mail_delete (source = (*src == '{') ?
+ mail_open (NIL,src,OP_HALFOPEN |
+ (debugp ? OP_DEBUG : NIL)) : NIL,src))
+ retcode = 0;
+ }
+ else if (!strcmp (cmd,"rename")) {
+ if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep)
+ printf (usage2,pgm,usgren,stdsw);
+ else if (mail_rename (source = (*src == '{') ?
+ mail_open (NIL,src,OP_HALFOPEN |
+ (debugp ? OP_DEBUG : NIL)) : NIL,src,dst))
+ retcode = 0;
+ }
+
+ else if ((i = !strcmp (cmd,"move")) || !strcmp (cmd,"copy")) {
+ if (!src || !dst || merge) printf (usage3,pgm,cmd,usgcpymov,stdsw);
+ else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) |
+ (debugp ? OP_DEBUG : NIL))) {
+ dest = NIL; /* open destination stream if network */
+ if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN |
+ (debugp ? OP_DEBUG : NIL)))) {
+ if (mbxcopy (source,dest,dst,T,i,merge)) retcode = 0;
+ }
+ }
+ }
+ else if ((i = !strcmp (cmd,"appenddelete")) || !strcmp (cmd,"append")) {
+ if (!src || !dst || merge) printf (usage3,pgm,cmd,usgappdel,stdsw);
+ else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) |
+ (debugp ? OP_DEBUG : NIL))) {
+ dest = NIL; /* open destination stream if network */
+ if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN |
+ (debugp ? OP_DEBUG : NIL)))) {
+ if (mbxcopy (source,dest,dst,NIL,i,merge)) retcode = 0;
+ }
+ }
+ }
+
+ else if (!strcmp (cmd,"prune")) {
+ if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep ||
+ !(criteria = prune_criteria (dst))) printf (usage2,pgm,usgprn,stdsw);
+ else if ((source = mail_open (NIL,src,(debugp ? OP_DEBUG : NIL))) &&
+ mail_search_full (source,NIL,criteria,SE_FREE)) {
+ for (m = 1, s = t = NIL, len = start = last = 0; m <= source->nmsgs; m++)
+ if (mail_elt (source,m)->searched) {
+ if (s) { /* continuing a range? */
+ if (m == last + 1) last = m;
+ else { /* no, end of previous range? */
+ if (last != start) sprintf (t,":%lu,%lu",last,m);
+ /* no, just this message */
+ else sprintf (t,",%lu",m);
+ start = last = m; /* either way, start new range */
+ /* running out of space? */
+ if ((len - (curlen = (t += strlen (t)) - s)) < 20) {
+ fs_resize ((void **) &s,len += MAILTMPLEN);
+ t = s + curlen; /* relocate current pointer */
+ }
+ }
+ }
+ else { /* first time, start new buffer */
+ s = (char *) fs_get (len = MAILTMPLEN);
+ sprintf (s,"%lu",start = last = m);
+ t = s + strlen (s); /* end of buffer */
+ }
+ }
+ /* finish last range if necessary */
+ if (last != start) sprintf (t,":%lu",last);
+ if (s) { /* delete/expunge any matching messages */
+ mail_flag (source,s,"\\Deleted",ST_SET);
+ m = source->nmsgs; /* get number of messages before purge */
+ mail_expunge (source);
+ printf ("%lu message(s) purged\n",m - source->nmsgs);
+ fs_give ((void **) &s); /* flush buffer */
+ }
+ else puts ("No matching messages, so nothing purged");
+ source = mail_close (source);
+ }
+ }
+
+ else if (!strcmp (cmd,"transfer")) {
+ if (!src || !dst) printf (usage2,pgm,usgxfr,stdsw);
+ else if ((*src == '{') && /* open source mailbox */
+ !(source = mail_open (NIL,src,OP_HALFOPEN |
+ (debugp ? OP_DEBUG : NIL))));
+ else if ((*dst == '{') && /* open destination server */
+ !(dest = mail_open (NIL,dst,OP_HALFOPEN |
+ (debugp ? OP_DEBUG : NIL))));
+ else if (!(f = tmpfile ())) puts ("can't open temporary file");
+ else {
+ if (verbosep) puts ("Listing mailboxes...");
+ if (dest) strcpy (strchr (strcpy (tmp,dest->mailbox),'}') + 1,
+ dp = strchr (dst,'}') + 1);
+ else {
+ dp = dst;
+ tmp[0] = '\0';
+ }
+ mail_list (dest,tmp,"");
+ rewind (f); /* list all mailboxes matching prefix */
+ if (ddelim < 0) { /* if server failed to give delimiter */
+ puts ("warning: unable to get destination hierarchy delimiter!");
+ ddelim = 0; /* default to none */
+ }
+ if (source) strcpy (strchr (strcpy (tmp,source->mailbox),'}') + 1,
+ strchr (src,'}') + 1);
+ else strcpy (tmp,src);
+ mail_list (source,tmp,"*");
+ rewind (f);
+ /* read back mailbox names */
+ for (retcode = 0; !retcode && (fgets (tmp,MAILTMPLEN-1,f)); ) {
+ if (t = strchr (tmp+1,'\n')) *t = '\0';
+ for (t = mbx,t1 = dest ? dest->mailbox : "",c = NIL; (c != '}') && *t1;
+ *t++ = c= *t1++);
+ for (t1 = dp; *t1; *t++ = *t1++);
+ /* point to name without delim or netspec */
+ t1 = source ? (strchr (tmp+1,'}') + 1) : tmp + 1;
+ /* src and mbx have different delimiters? */
+ if (ddelim && (ddelim != tmp[0]))
+ while (c = *t1++) { /* swap delimiters then */
+ if (c == ddelim) c = tmp[0] ? tmp[0] : 'x';
+ else if (c == tmp[0]) c = ddelim;
+ *t++ = c;
+ }
+ /* easy case */
+ else while (*t1) *t++ = *t1++;
+ *t++ = '\0';
+ if (verbosep) {
+ printf ("Copying %s\n => %s\n",tmp+1,mbx);
+ fflush (stdout);
+ }
+ if (source = mail_open (source,tmp+1,(debugp ? OP_DEBUG : NIL) |
+ (rwcopyp ? NIL : OP_READONLY))) {
+ if (!mbxcopy (source,dest,mbx,T,NIL,merge)) retcode = 1;
+ if (source->dtb->flags & DR_LOCAL) source = mail_close (source);
+ }
+ else printf ("can't open source mailbox %s\n",tmp+1);
+ }
+ }
+ }
+
+ else {
+ printf ("%s version %s.%s\n\n",pgm,CCLIENTVERSION,version);
+ printf (usage2,pgm,"command [switches] arguments",stdsw);
+ printf ("\nCommands:\n %s\n",usgchk);
+ puts (" ;; report number of messages and new messages");
+ printf (" %s\n",usgcre);
+ puts (" ;; create new mailbox");
+ printf (" %s\n",usgdel);
+ puts (" ;; delete existing mailbox");
+ printf (" %s\n",usgren);
+ puts (" ;; rename mailbox to a new name");
+ printf (" copy %s\n",usgcpymov);
+ printf (" move %s\n",usgcpymov);
+ puts (" ;; create new mailbox and copy/move messages");
+ printf (" append %s\n",usgappdel);
+ printf (" appenddelete %s\n",usgappdel);
+ puts (" ;; copy/move messages to existing mailbox");
+ printf (" %s\n",usgprn);
+ puts (" ;; prune mailbox of messages matching criteria");
+ printf (" %s\n",usgxfr);
+ puts (" ;; copy source hierarchy to destination");
+ puts (" ;; -merge modes are prompt, append, or suffix=xxxx");
+ }
+ /* close streams */
+ if (source) mail_close (source);
+ if (dest) mail_close (dest);
+ exit (retcode);
+ return retcode; /* stupid compilers */
+}
+
+/* Pruning criteria, somewhat extended from mail_criteria()
+ * Accepts: criteria
+ * Returns: search program if parse successful, else NIL
+ */
+
+SEARCHPGM *prune_criteria (char *criteria)
+{
+ SEARCHPGM *pgm = NIL;
+ char *criterion,*r,tmp[MAILTMPLEN];
+ int f;
+ if (criteria) { /* only if criteria defined */
+ /* make writeable copy of criteria */
+ criteria = cpystr (criteria);
+ /* for each criterion */
+ for (pgm = mail_newsearchpgm (), criterion = strtok_r (criteria," ",&r);
+ criterion; (criterion = strtok_r (NIL," ",&r))) {
+ f = NIL; /* init then scan the criterion */
+ switch (*ucase (criterion)) {
+ case 'A': /* possible ALL, ANSWERED */
+ if (!strcmp (criterion+1,"LL")) f = T;
+ else if (!strcmp (criterion+1,"NSWERED")) f = pgm->answered = T;
+ break;
+ case 'B': /* possible BCC, BEFORE, BODY */
+ if (!strcmp (criterion+1,"CC"))
+ f = mail_criteria_string (&pgm->bcc,&r);
+ else if (!strcmp (criterion+1,"EFORE"))
+ f = mail_criteria_date (&pgm->before,&r);
+ else if (!strcmp (criterion+1,"ODY"))
+ f = mail_criteria_string (&pgm->body,&r);
+ break;
+ case 'C': /* possible CC */
+ if (!strcmp (criterion+1,"C")) f = mail_criteria_string (&pgm->cc,&r);
+ break;
+ case 'D': /* possible DELETED, DRAFT */
+ if (!strcmp (criterion+1,"ELETED")) f = pgm->deleted = T;
+ else if (!strcmp (criterion+1,"RAFT")) f = pgm->draft = T;
+ break;
+ case 'F': /* possible FLAGGED, FROM */
+ if (!strcmp (criterion+1,"LAGGED")) f = pgm->flagged = T;
+ else if (!strcmp (criterion+1,"ROM"))
+ f = mail_criteria_string (&pgm->from,&r);
+ break;
+ case 'K': /* possible KEYWORD */
+ if (!strcmp (criterion+1,"EYWORD"))
+ f = mail_criteria_string (&pgm->keyword,&r);
+ break;
+ case 'L': /* possible LARGER */
+ if (!strcmp (criterion+1,"ARGER"))
+ f = prune_criteria_number (&pgm->larger,&r);
+
+ case 'N': /* possible NEW */
+ if (!strcmp (criterion+1,"EW")) f = pgm->recent = pgm->unseen = T;
+ break;
+ case 'O': /* possible OLD, ON */
+ if (!strcmp (criterion+1,"LD")) f = pgm->old = T;
+ else if (!strcmp (criterion+1,"N"))
+ f = mail_criteria_date (&pgm->on,&r);
+ break;
+ case 'R': /* possible RECENT */
+ if (!strcmp (criterion+1,"ECENT")) f = pgm->recent = T;
+ break;
+ case 'S': /* possible SEEN, SENT*, SINCE, SMALLER,
+ SUBJECT */
+ if (!strcmp (criterion+1,"EEN")) f = pgm->seen = T;
+ else if (!strncmp (criterion+1,"ENT",3)) {
+ if (!strcmp (criterion+4,"BEFORE"))
+ f = mail_criteria_date (&pgm->sentbefore,&r);
+ else if (!strcmp (criterion+4,"ON"))
+ f = mail_criteria_date (&pgm->senton,&r);
+ else if (!strcmp (criterion+4,"SINCE"))
+ f = mail_criteria_date (&pgm->sentsince,&r);
+ }
+ else if (!strcmp (criterion+1,"INCE"))
+ f = mail_criteria_date (&pgm->since,&r);
+ else if (!strcmp (criterion+1,"MALLER"))
+ f = prune_criteria_number (&pgm->smaller,&r);
+ else if (!strcmp (criterion+1,"UBJECT"))
+ f = mail_criteria_string (&pgm->subject,&r);
+ break;
+ case 'T': /* possible TEXT, TO */
+ if (!strcmp (criterion+1,"EXT"))
+ f = mail_criteria_string (&pgm->text,&r);
+ else if (!strcmp (criterion+1,"O"))
+ f = mail_criteria_string (&pgm->to,&r);
+ break;
+ case 'U': /* possible UN* */
+ if (criterion[1] == 'N') {
+ if (!strcmp (criterion+2,"ANSWERED")) f = pgm->unanswered = T;
+ else if (!strcmp (criterion+2,"DELETED")) f = pgm->undeleted = T;
+ else if (!strcmp (criterion+2,"DRAFT")) f = pgm->undraft = T;
+ else if (!strcmp (criterion+2,"FLAGGED")) f = pgm->unflagged = T;
+ else if (!strcmp (criterion+2,"KEYWORD"))
+ f = mail_criteria_string (&pgm->unkeyword,&r);
+ else if (!strcmp (criterion+2,"SEEN")) f = pgm->unseen = T;
+ }
+ break;
+ default: /* we will barf below */
+ break;
+ }
+
+ if (!f) { /* if can't identify criterion */
+ sprintf (tmp,"Unknown search criterion: %.30s",criterion);
+ MM_LOG (tmp,ERROR);
+ mail_free_searchpgm (&pgm);
+ break;
+ }
+ }
+ /* no longer need copy of criteria */
+ fs_give ((void **) &criteria);
+ }
+ return pgm;
+}
+
+
+/* Parse a number
+ * Accepts: pointer to integer to return
+ * pointer to strtok state
+ * Returns: T if successful, else NIL
+ */
+
+int prune_criteria_number (unsigned long *number,char **r)
+{
+ char *t;
+ STRINGLIST *s = NIL;
+ /* parse the date and return fn if OK */
+ int ret = (mail_criteria_string (&s,r) &&
+ (*number = strtoul ((char *) s->text.data,&t,10)) && !*t) ?
+ T : NIL;
+ if (s) mail_free_stringlist (&s);
+ return ret;
+}
+
+/* Copy mailbox
+ * Accepts: stream open on source
+ * halfopen stream for destination or NIL
+ * destination mailbox name
+ * non-zero to create destination mailbox
+ * non-zero to delete messages from source after copying
+ * merge mode
+ * Returns: T if success, NIL if error
+ */
+
+int mbxcopy (MAILSTREAM *source,MAILSTREAM *dest,char *dst,int create,int del,
+ int mode)
+{
+ char *s,tmp[MAILTMPLEN];
+ APPENDPACKAGE ap;
+ STRING st;
+ char *ndst = NIL;
+ int ret = NIL;
+ trycreate = NIL; /* no TRYCREATE yet */
+ if (create) while (!mail_create (dest,dst) && (mode != mAPPEND)) {
+ switch (mode) {
+ case mPROMPT: /* prompt user for new name */
+ tmp[0] = '\0';
+ while (!tmp[0]) { /* read name */
+ fputs ("alternative name: ",stdout);
+ fflush (stdout);
+ fgets (tmp,MAILTMPLEN-1,stdin);
+ if (s = strchr (tmp,'\n')) *s = '\0';
+ }
+ if (ndst) fs_give ((void **) &ndst);
+ ndst = cpystr (tmp);
+ break;
+ case mSUFFIX: /* try again with new suffix */
+ if (ndst) fs_give ((void **) &ndst);
+ sprintf (ndst = (char *) fs_get (strlen (dst) + strlen (suffix) + 1),
+ "%s%s",dst,suffix);
+ printf ("retry to create %s\n",ndst);
+ mode = mPROMPT; /* switch to prompt mode if name fails */
+ break;
+ case NIL: /* not merging */
+ return NIL;
+ }
+ if (ndst) dst = ndst; /* if alternative name given, use it */
+ }
+
+ if (kwcopyp) {
+ int i;
+ size_t len;
+ char *dummymsg = "Date: Thu, 18 May 2006 00:00 -0700\r\nFrom: dummy@example.com\r\nSubject: dummy\r\n\r\ndummy\r\n";
+ for (i = 0,len = 0; i < NUSERFLAGS; ++i)
+ if (source->user_flags[i]) len += strlen (source->user_flags[i]) + 1;
+ if (len) { /* easy if no user flags to copy... */
+ char *t;
+ char *tail = "\\Deleted)";
+ char *flags = (char *) fs_get (1 + len + strlen (tail) + 1);
+ s = flags; *s++ = '(';
+ for (i = 0; i < NUSERFLAGS; ++i) if (t = source->user_flags[i]) {
+ while (*t) *s++ = *t++;
+ *s++ = ' ';
+ }
+ strcpy (s,tail); /* terminate flags list */
+ if ((dst[0] == '#') && ((dst[1] == 'D') || (dst[1] == 'd')) &&
+ ((dst[2] == 'R') || (dst[2] == 'r')) &&
+ ((dst[3] == 'I') || (dst[3] == 'i')) &&
+ ((dst[4] == 'V') || (dst[4] == 'v')) &&
+ ((dst[5] == 'E') || (dst[5] == 'e')) &&
+ ((dst[6] == 'R') || (dst[6] == 'r')) && (dst[7] == '.') &&
+ (t = strchr (dst+8,'/'))) ++t;
+ else t = dst;
+ INIT (&st,mail_string,dummymsg,strlen (dummymsg));
+ if (!(mail_append (dest,dst,&st) &&
+ (dest = mail_open (dest,t,debugp ? OP_DEBUG : NIL)))) {
+ fs_give ((void **) &flags);
+ return NIL;
+ }
+ mail_setflag (dest,"*",flags);
+ mail_expunge (dest);
+ fs_give ((void **) &flags);
+ }
+ }
+
+ if (source->nmsgs) { /* non-empty source */
+ if (verbosep) printf ("%s [%lu message(s)] => %s\n",
+ source->mailbox,source->nmsgs,dst);
+ ap.stream = source; /* prepare append package */
+ ap.msgno = 0;
+ ap.msgmax = source->nmsgs;
+ ap.flags = ap.date = NIL;
+ ap.message = &st;
+ /* make sure we have all messages */
+ sprintf (tmp,"1:%lu",ap.msgmax);
+ mail_fetchfast (source,tmp);
+ if (mail_append_multiple (dest,dst,mm_append,(void *) &ap)) {
+ --ap.msgno; /* make sure user knows it won */
+ if (verbosep) printf ("[Ok %lu messages(s)]\n",ap.msgno);
+ if (del && ap.msgno) { /* delete source messages */
+ sprintf (tmp,"1:%lu",ap.msgno);
+ mail_flag (source,tmp,"\\Deleted",ST_SET);
+ /* flush moved messages */
+ mail_expunge (source);
+ }
+ ret = T;
+ }
+ else if ((mode == mAPPEND) && trycreate)
+ ret = mbxcopy (source,dest,dst,create,del,mPROMPT);
+ else if (verbosep) puts ("[Failed]");
+ }
+ else { /* empty source */
+ if (verbosep) printf ("%s [empty] => %s\n",source->mailbox,dst);
+ ret = T;
+ }
+ if (ndst) fs_give ((void **) &ndst);
+ return ret;
+}
+
+/* Append callback
+ * Accepts: mail stream
+ * append package
+ * pointer to return flags
+ * pointer to return date
+ * pointer to return message stringstruct
+ * Returns: T on success
+ */
+
+long mm_append (MAILSTREAM *stream,void *data,char **flags,char **date,
+ STRING **message)
+{
+ char *t,*t1,tmp[MAILTMPLEN];
+ unsigned long u;
+ MESSAGECACHE *elt;
+ APPENDPACKAGE *ap = (APPENDPACKAGE *) data;
+ *flags = *date = NIL; /* assume no flags or date */
+ if (ap->flags) fs_give ((void **) &ap->flags);
+ if (ap->date) fs_give ((void **) &ap->date);
+ mail_gc (ap->stream,GC_TEXTS);
+ if (++ap->msgno <= ap->msgmax) {
+ /* initialize flag string */
+ memset (t = tmp,0,MAILTMPLEN);
+ /* output system flags */
+ if ((elt = mail_elt (ap->stream,ap->msgno))->seen) strcat (t," \\Seen");
+ if (elt->deleted) strcat (t," \\Deleted");
+ if (elt->flagged) strcat (t," \\Flagged");
+ if (elt->answered) strcat (t," \\Answered");
+ if (elt->draft) strcat (t," \\Draft");
+ /* any user flags? */
+ if (!ignorep && (u = elt->user_flags)) do
+ if ((t1 = ap->stream->user_flags[find_rightmost_bit (&u)]) &&
+ (MAILTMPLEN - ((t += strlen (t)) - tmp)) > (long) (2 + strlen (t1))){
+ *t++ = ' '; /* space delimiter */
+ strcpy (t,t1); /* copy the user flag */
+ }
+ while (u); /* until no more user flags */
+ *flags = ap->flags = cpystr (tmp + 1);
+ *date = ap->date = cpystr (mail_date (tmp,elt));
+ *message = ap->message; /* message stringstruct */
+ INIT (ap->message,mstring,(void *) ap,elt->rfc822_size);
+ }
+ else *message = NIL; /* all done */
+ return LONGT;
+}
+
+/* Co-routines from MAIL library */
+
+
+/* Message matches a search
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_searched (MAILSTREAM *stream,unsigned long msgno)
+{
+ /* dummy routine */
+}
+
+
+/* Message exists (i.e. there are that many messages in the mailbox)
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_exists (MAILSTREAM *stream,unsigned long number)
+{
+ /* dummy routine */
+}
+
+
+/* Message expunged
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_expunged (MAILSTREAM *stream,unsigned long number)
+{
+ /* dummy routine */
+}
+
+
+/* Message flags update seen
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_flags (MAILSTREAM *stream,unsigned long number)
+{
+ /* dummy routine */
+}
+
+/* Mailbox found
+ * Accepts: MAIL stream
+ * hierarchy delimiter
+ * mailbox name
+ * mailbox attributes
+ */
+
+void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
+{
+ /* note destination delimiter */
+ if (ddelim < 0) ddelim = delimiter;
+ /* if got a selectable name */
+ else if (!(attributes & LATT_NOSELECT) && *name)
+ fprintf (f,"%c%s\n",delimiter,name);
+}
+
+
+/* Subscribe mailbox found
+ * Accepts: MAIL stream
+ * hierarchy delimiter
+ * mailbox name
+ * mailbox attributes
+ */
+
+void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
+{
+ /* dummy routine */
+}
+
+
+/* Mailbox status
+ * Accepts: MAIL stream
+ * mailbox name
+ * mailbox status
+ */
+
+void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
+{
+ if (status->recent || status->unseen)
+ printf ("%lu new message(s) (%lu unseen),",status->recent,status->unseen);
+ else fputs ("No new messages,",stdout);
+ printf (" %lu total in %s\n",status->messages,mailbox);
+}
+
+/* Notification event
+ * Accepts: MAIL stream
+ * string to log
+ * error flag
+ */
+
+void mm_notify (MAILSTREAM *stream,char *string,long errflg)
+{
+ if (!errflg && (string[0] == '[') &&
+ ((string[1] == 'T') || (string[1] == 't')) &&
+ ((string[2] == 'R') || (string[2] == 'r')) &&
+ ((string[3] == 'Y') || (string[3] == 'y')) &&
+ ((string[4] == 'C') || (string[4] == 'c')) &&
+ ((string[5] == 'R') || (string[5] == 'r')) &&
+ ((string[6] == 'E') || (string[6] == 'e')) &&
+ ((string[7] == 'A') || (string[7] == 'a')) &&
+ ((string[8] == 'T') || (string[8] == 't')) &&
+ ((string[9] == 'E') || (string[9] == 'e')) &&
+ (string[10] == ']'))
+ trycreate = T;
+ mm_log (string,errflg); /* just do mm_log action */
+}
+
+
+/* Log an event for the user to see
+ * Accepts: string to log
+ * error flag
+ */
+
+void mm_log (char *string,long errflg)
+{
+ switch (errflg) {
+ case BYE:
+ case NIL: /* no error */
+ if (verbosep) fprintf (stderr,"[%s]\n",string);
+ break;
+ case PARSE: /* parsing problem */
+ case WARN: /* warning */
+ fprintf (stderr,"warning: %s\n",string);
+ break;
+ case ERROR: /* error */
+ default:
+ fprintf (stderr,"%s\n",string);
+ break;
+ }
+}
+
+
+/* Log an event to debugging telemetry
+ * Accepts: string to log
+ */
+
+void mm_dlog (char *string)
+{
+ fprintf (stderr,"%s\n",string);
+}
+
+/* Get user name and password for this host
+ * Accepts: parse of network mailbox name
+ * where to return user name
+ * where to return password
+ * trial count
+ */
+
+void mm_login (NETMBX *mb,char *username,char *password,long trial)
+{
+ char *s,tmp[MAILTMPLEN];
+ sprintf (s = tmp,"{%s/%s",mb->host,mb->service);
+ if (*mb->user) sprintf (tmp+strlen (tmp),"/user=%s",
+ strcpy (username,mb->user));
+ if (*mb->authuser) sprintf (tmp+strlen (tmp),"/authuser=%s",mb->authuser);
+ if (*mb->user) strcat (s = tmp,"} password:");
+ else {
+ printf ("%s} username: ",tmp);
+ fgets (username,NETMAXUSER-1,stdin);
+ username[NETMAXUSER-1] = '\0';
+ if (s = strchr (username,'\n')) *s = '\0';
+ s = "password: ";
+ }
+ strcpy (password,getpass (s));
+}
+
+
+/* About to enter critical code
+ * Accepts: stream
+ */
+
+void mm_critical (MAILSTREAM *stream)
+{
+ critical = T; /* note in critical code */
+}
+
+
+/* About to exit critical code
+ * Accepts: stream
+ */
+
+void mm_nocritical (MAILSTREAM *stream)
+{
+ critical = NIL; /* note not in critical code */
+}
+
+
+/* Disk error found
+ * Accepts: stream
+ * system error code
+ * flag indicating that mailbox may be clobbered
+ * Returns: T if user wants to abort
+ */
+
+long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
+{
+ return T;
+}
+
+
+/* Log a fatal error event
+ * Accepts: string to log
+ */
+
+void mm_fatal (char *string)
+{
+ fprintf (stderr,"FATAL: %s\n",string);
+}
diff --git a/imap/src/mailutil/makefile.nt b/imap/src/mailutil/makefile.nt
new file mode 100644
index 00000000..1a6eb515
--- /dev/null
+++ b/imap/src/mailutil/makefile.nt
@@ -0,0 +1,50 @@
+# ========================================================================
+# 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
+#
+#
+# ========================================================================
+
+
+# Program: MAILUTIL Makefile for Windows 9x and Windows NT
+#
+# Author: Mark Crispin
+# Networks and Distributed Computing
+# Computing & Communications
+# University of Washington
+# Administration Building, AG-44
+# Seattle, WA 98195
+# Internet: MRC@CAC.Washington.EDU
+#
+# Date: 25 February 1996
+# Last Edited: 30 August 2006
+
+
+C = ..\c-client
+CCLIENTLIB = $C\cclient.lib
+LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib
+CFLAGS= -I$C /MT /W3 /DWIN32 /D_WIN32_WINNT=0x0400 -nologo $(EXTRACFLAGS)
+OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
+VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
+CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
+
+mailutil: $(CCLIENTLIB) mailutil.obj
+ LINK /NOLOGO mailutil.obj $(LIBS)
+
+mailutil.obj: $C\mail.h $C\smtp.h $C\misc.h $C\osdep.h mailutil.c
+
+$(CCLIENTLIB):
+ @echo Make c-client first
+ false
+
+clean:
+ del *.obj *.exe *.lib *.exp || rem
+
+# A monument to a hack of long ago and far away...
+love:
+ @echo not war?
diff --git a/imap/src/mailutil/makefile.ntk b/imap/src/mailutil/makefile.ntk
new file mode 100644
index 00000000..42ae5185
--- /dev/null
+++ b/imap/src/mailutil/makefile.ntk
@@ -0,0 +1,51 @@
+# ========================================================================
+# 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
+#
+#
+# ========================================================================
+
+
+# Program: MAILUTIL Makefile for Windows 9x and Windows NT + Kerberos
+#
+# Author: Mark Crispin
+# Networks and Distributed Computing
+# Computing & Communications
+# University of Washington
+# Administration Building, AG-44
+# Seattle, WA 98195
+# Internet: MRC@CAC.Washington.EDU
+#
+# Date: 25 February 1996
+# Last Edited: 30 August 2006
+
+
+C = ..\c-client
+CCLIENTLIB = $C\cclient.lib
+K5 = \k5\lib
+K5LIB = $(K5)\comerr32.lib $(K5)\gssapi32.lib $(K5)\krb5_32.lib
+LIBS = $(CCLIENTLIB) $(K5LIB) ws2_32.lib winmm.lib advapi32.lib
+OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
+VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
+CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
+
+mailutil: $(CCLIENTLIB) mailutil.obj
+ LINK /NOLOGO mailutil.obj $(LIBS)
+
+mailutil.obj: $C\mail.h $C\smtp.h $C\misc.h $C\osdep.h mailutil.c
+
+$(CCLIENTLIB):
+ @echo Make c-client first
+ false
+
+clean:
+ del *.obj *.exe *.lib *.exp || rem
+
+# A monument to a hack of long ago and far away...
+love:
+ @echo not war?
diff --git a/imap/src/mailutil/makefile.w2k b/imap/src/mailutil/makefile.w2k
new file mode 100644
index 00000000..7f0c4614
--- /dev/null
+++ b/imap/src/mailutil/makefile.w2k
@@ -0,0 +1,49 @@
+# ========================================================================
+# 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
+#
+#
+# ========================================================================
+
+
+# Program: MAILUTIL Makefile for Windows 2000/XP
+#
+# Author: Mark Crispin
+# Networks and Distributed Computing
+# Computing & Communications
+# University of Washington
+# Administration Building, AG-44
+# Seattle, WA 98195
+# Internet: MRC@CAC.Washington.EDU
+#
+# Date: 25 February 1996
+# Last Edited: 30 August 2006
+
+
+C = ..\c-client
+CCLIENTLIB = $C\cclient.lib
+LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib secur32.lib crypt32.lib
+OSCOMPAT = /DWIN32
+VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
+CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
+
+mailutil: $(CCLIENTLIB) mailutil.obj
+ LINK /NOLOGO mailutil.obj $(LIBS)
+
+mailutil.obj: $C\mail.h $C\smtp.h $C\misc.h $C\osdep.h mailutil.c
+
+$(CCLIENTLIB):
+ @echo Make c-client first
+ false
+
+clean:
+ del *.obj *.exe *.lib *.exp || rem
+
+# A monument to a hack of long ago and far away...
+love:
+ @echo not war?