help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: reading mail with emacs


From: visaris tds.net
Subject: Re: reading mail with emacs
Date: Wed, 13 Aug 2014 21:14:41 -0400

I managed to throw together some c code that does the quick-and-dirty (with
my mail at least).  Here it is in case anyone finds it useful...

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

long   PageSize,Start,End,Count,Debug;
char  *Path,*Address,*Date;
off_t  H_size, B_size;

char *found(char *p, char t, int d, long l) // string, target, delta, count
{
  while (l-- > 0){
    if (*p == t) return p;
    p = p+d;
  }
  return NULL;
}

char *locate(char *p, char *t, int d, long l) // string, target, delta,
count
{
  char *q;

  while (*t){
    if ((q = found(p,*t,d,l))){
      if (*++t){
    l -= 1+ ((d>0)? (q-p)/d: -(p-q)/d);
    p  = q+d;
    continue;
      }
      return q;
    }
    return NULL;
  }
  return NULL;
}

char *find(char *p, char *t, long l) // string, target, bound
{
  char *q,*r;

  if (strlen(t) < 2) return locate(p,t,1,l);

  while ((q = found(p,*t,1,l))){
    if (r = find(q+1,t+1,l-(q-p)-1)){
      if (*t == r[-1]) return r-1;
      l -= r-p;
      p  = r;
      continue;
    }
    return NULL;
  }
  return NULL;
}

long address(char *p)
{
  char *s,*e;  long i = H_size;

  Address = NULL;
  if ((s = locate(p,"\n\n",1,i))){
    if (*++s == '<'){
      i -= s-p;
      if ((e = found(s,'\n',1,i))){
    if (*--e == '>'){
      if (e-s > 1){
        Address = ++s;
        return e-s;
      }
    }
      }
    }
  }
  return 0;
}

int date(char *p)
{
  static char buf[512];
  char *s,*e,d[64],n[64],m[64],y[64],t[64],z[64];  long i = H_size;

  Date = NULL;
  if ((s = find(p,"Date: ",i))){
    i -= s-p;
    if ((e = found(s,'\n',1,i))&&(e-s < 64)){
      strncpy(buf,s,63); buf[63] = 0;
      if (6 == sscanf(buf,"Date: %s %s %s %s %s %s",d,n,m,y,t,z)){
    if ((s = index(d,','))) *s = 0;
    sprintf(buf," %s %s %s %s %s\n",d,m,n,t,y);
    if (strlen(buf) < 64){
      Date = buf;
      return 1;
    }
      }
    }
  }
  return 0;
}

void dump(char *p, char *t, char *r)
{
  char *s,*e;  long i = H_size;

  if ((s = find(p,t,i))){
    if ((e = found(s,'\n',1,i))){
      if (r){
    s += strlen(t);
    printf("%s",r);
      }
      do putchar(*s); while (s++ < e);
    }
  }
}

void content_type(char *p)
{
  char *s,*e;  long i = H_size;

  if ((s = find(p,"Content-Type: ",i))){
    if ((e = found(s,'\n',1,i))){
      do putchar(*s); while (s++ < e);
      s = e+1;
      while (*++e) if (*e == '\n') break;
      if ((*e)&&(s = find(s,"boundary",e-s))){
    putchar('\t');
    do putchar(*s); while (s++ < e);
      }
    }
  }
}

void user_agent(char *p)
{
  char *s,*e;  long i = H_size;

  printf("User-Agent: (%ld) ", Count);
  if ((s = find(p,"User-Agent: ",i))){
    if ((e = found(s,'\n',1,i))){
      s += 12; e--;
      do putchar(*s); while (s++ < e);
    }
  }
  putchar('\n');
}

size_t head(char *h)
{
  long i,j;

  if (Debug){
    for (i = 0; i < H_size; i++){
      fputc(h[i], stderr);
    }
  }
  if ((i = address(h))){
    printf("From ");
    for (j = 0; j < i; j++) putchar(Address[j]);
    if (date(h))
      printf("%s",Date);

    //    printf("X-Coding-System: undecided-unix\n");

    dump(h,"Date: "               , NULL           );
    //    dump(h,"From: "               , ">From: "      );
    dump(h,"From: "               , NULL           );
    dump(h,"To: "                 , NULL           );
    dump(h,"Subject: "            , NULL           );
    dump(h,"Message-ID: "         , NULL           );
    dump(h,"References: "         , NULL           );
    dump(h,"MIME-Version: "       ,"Mime-Version: ");
    dump(h,"X-MimeOLE: "          , NULL           );
    content_type(h);
    dump(h,"Content-Disposition: ", NULL           );
    dump(h,"In-Reply-To: "        , NULL           );
    user_agent(h);
    printf("X-RMAIL-ATTRIBUTES: --------\n");
    putchar('\n');
  }
  return PageSize*(1+(H_size-1)/PageSize);
}

size_t body(char *b)
{
  unsigned long i;

  if (Debug){
    for (i = 0; i < B_size; i++){
      fputc(b[i], stderr);
    }
  }
  if (Address){
    for (i = 0; i < B_size; i++){
      if (b[i] == '\n')
    break;
    }
    while (++i < B_size) putchar(b[i]);
    putchar('\n');
  }
  return PageSize*(1+(B_size-1)/PageSize);
}

void message(char *n) // convert and dump to stdout
{
  struct stat st;
  void *p,*q; char *s, name[1024], buf[1024];  int h,b;  size_t hl, bl;

  if ((Start > ++Count)||(Count > End)) return;

  if ((-1 == (h = open(n, O_RDONLY)))){             // open headder?
    fprintf(stderr,"can't open %s\n", n);
    return;
  }
  if (fstat(h,&st)){
    fprintf(stderr, "can't stat %s\n", n);
    close(h);
    return;
  }
  H_size = st.st_size;
  if (!(p = mmap(0, H_size, PROT_READ, MAP_PRIVATE, h, 0))){
    fprintf(stderr, "can't mmap %s\n", n);
    close(h);
    return;
  }
  for (s = n; *s; s++);
  while (*s^'/') s--;
  if ((1^sscanf((char *)p, "%1000s", name))||(strcmp(++s, name))){
    fprintf(stderr,"file %s: format error\n", n);
    munmap(p,hl);
    close(h);
    return;
  }
  for (s = n; *s; s++);
  s[-1] = 'D';
  if ((-1 == (b = open(n, O_RDONLY)))){             // open body?
    fprintf(stderr,"can't open %s\n", n);
    munmap(p,hl);
    close(h);
    return;
  }
  if (fstat(b,&st)){
    fprintf(stderr, "can't stat %s\n", n);
    munmap(p,hl);
    close(h);
    return;
  }
  B_size = st.st_size;
  if (!(q = mmap(0, B_size, PROT_READ, MAP_PRIVATE, b, 0))){
    fprintf(stderr, "can't mmap %s\n", n);
    munmap(p,hl);
    close(h);
    close(b);
    return;
  }
  for (s = n; *s; s++);
  while (*s^'/') s--;
  if ((1^sscanf((char *)q, "%1000s", name))||(strcmp(++s, name))){
    fprintf(stderr,"file %s: format error\n", n);
    munmap(p,hl);
    close(h);
    munmap(q,bl);
    close(b);
    return;
  }
  hl = head((char *)p);
  bl = body((char *)q);
  munmap(p,hl);
  munmap(q,bl);
  close(h);
  close(b);
}

main(int argc, char *argv[])
{
  char *p,*q, buf[4096];  int i,j;   DIR *dirp;  struct dirent *d;

  if (argc^4) goto usage;
  Debug = atoi(argv[1]);
  Start = atoi(argv[2]);
  End   = atoi(argv[3]);

  if (!(p = argv[4])){
  usage:
    printf("usage: access debug start end path\n"
       "where debug is 0 or 1, \n"
       "start and end are integers (range of messages to convert)\n"
       "and path is for example /var/spool/exim/input \n"
       "(locking needs to be added, and it is most certainly incomplete and
buggy)\n");
    return 1;
  }
  for (i = 0; i < 3072; i++, p++){                  // copy path to buf
    if ((buf[i] = *p)) continue;
    break;
  }
  if (*(p = buf+i)){                                // p is buf at end of
path
    goto usage;
  }
  if (!(dirp = opendir(buf))){
    fprintf(stderr,"can't open %s\n",p);
    return 1;
  }
  PageSize = sysconf(_SC_PAGE_SIZE);
  if (*--p^'/') *++p = '/';                         // terminate path with
'/'
  while ((d = readdir(dirp))){
    for (i = 1, q = d->d_name; i < 1000; i++, q++){
      if ((p[i] = *q)) continue;
      break;
    }
    if ((*q)||(q[-1]^'H')) continue;                // find headder files
    message(buf);                                   // convert and dump to
stdout
  }
  closedir(dirp);
  return 0;
}
/*
gcc -g -o access access.c
*/



On Wed, Aug 13, 2014 at 3:56 PM, visaris tds.net <visaris@tds.net> wrote:

> I know movemail purportedly can transfer email from mysterious places to
> wherever emacs needs to find it, but I don't know how to make movemail work
> (I've read the documentation several times, but find it baffling).
>
> I wrote c code to move messages from /var/spool/input to an RMAIL file,
> but I evidently have not guessed correctly as to the exact file format
> emacs needs (M-x rmail complains
> and chokes on the RMAIL file I generate).
>
> I thought exim was a MTA.  I thought it already puts mail in a spool file.
> All my mail is in /var/spool/exim/input. I believe that exim could be
> configured somehow to allow emacs to read mail, but I don't know how.
>
> I stumbled across a mailing list for exim.  Perhaps I need to start there.
>
>
> On Tue, Aug 12, 2014 at 9:18 PM, Robert Thorpe <
> rt@robertthorpeconsulting.com> wrote:
>
>> "visaris tds.net" <visaris@tds.net> writes:
>>
>> > Whereas I have been reading mail with emacs for decades, I did a new
>> install
>> > (I'm a gentoo user) and now what once automagically worked nolonger
>> does...
>> > Emacs seems to function -- exept for mail.
>> >
>> > Although I have fethcmail and exim running, and although mail does
>> > arive in /var/spool/exim/input, the format is that each message is split
>> > into
>> > a header file and then the body of the message.
>> >
>> > M-x rmail does not get mail from  /var/spool/exim/input.
>>
>> Did you post about this to the Emacs Reddit group recently?  As someone
>> else wrote there /var/spool/exim/input is Exim's *input* spool file.
>> It's where Exim puts emails before they are delivered.  As far as I
>> understand it Exim is not designed to have users get stuff from that
>> directory.  In the past it may have only worked by coincidence, because
>> older versions of Exim stored stuff in some format that movemail
>> understands.
>>
>> > I have spent much time chasing cryptic pointers reading unintelligable
>> > documents making vague references to "movemail" but it is beyond me.
>> > I have contemplated perusing the RMAIL file and comparing it with
>> > contents of /var/spool/exim/input so as to increase the chance that I
>> can
>> > make some lucky guesses and write a c program to bridge the gap from
>> > /var/spool/exim/input to RMAIL.  Surely emacs has not deteriated to the
>> > point that this would be necessary.  I find it difficult to believe
>> there
>> > is not
>> >  some simple way to proceed.
>>
>> "Movemail" fulfills two purposes.  Firstly, it moves mails between
>> different places on one system.  It can take mail from the spool file(s)
>> to a mbox file in the user's home directory.  (If the spool file is in
>> MH or Maildir format it can translate that to mbox).  Secondly, it can
>> act rather like fetchmail, it can download mails from an IMAP or POP
>> server and copy them to a mbox file in the user's home directory.
>>
>> After movemail has done it's thing rmail itself takes over.  Rmail is
>> really just a viewer for mbox files.  Rmail runs movemail automatically,
>> there's no need to run it manually.
>>
>> If you have an MTA setup then it's normal to use it in the first way.
>> The MTA puts mail in a spool file.  Then when you do M-x rmail it calls
>> movemail which moves it to the "RMAIL" file in your home directory.
>> That's what happens if you set the MAIL environment variable to your
>> spool file.  If you want to make that approach work you need to figure
>> out Exim (I find its manual baffling).  One way that could work is to
>> use the LMTP transport of Exim to communicate with a mail delivery
>> program such as maidag or maildrop.  Those programs put mail into spool
>> files for users to access.  In this case you'll have:
>> fetchmail(MRA)->Exim(MTA)->Maidag(MDA)->SpoolFile->movemail->rmail.
>>
>> Alternatively, you can bring mail directly from your IMAP or POP server
>> using movemail.  That's what I do, I don't run an MTA on my PC at all, I
>> deliver using Emac's smtpmail library.  To do this do something like:
>> (setq send-mail-function 'smtpmail-send-it)
>> (setq smtpmail-smtp-server "smtp.yourisp.com")
>> (setq rmail-primary-inbox-list
>>   '("imap://yourlogin:password@imap.yourisp.com"))
>>
>> To use IMAP you need the version of movemail in the GNU mailutils
>> package.  The one that comes with Emacs only supports POP.
>>
>> BR,
>> Robert Thorpe
>>
>
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]