From: "visaris tds.net" <visaris@tds.net>
To: Robert Thorpe <rt@robertthorpeconsulting.com>
Cc: help-gnu-emacs@gnu.org
Subject: Re: reading mail with emacs
Date: Wed, 13 Aug 2014 21:14:41 -0400 [thread overview]
Message-ID: <CA+Jy_pCCs2=fqA9jVjc9OqQrrmXFOxxtiHA+=-+YGJVrqL80nA@mail.gmail.com> (raw)
In-Reply-To: <CA+Jy_pASyaNiFxAoNF-+P0fhpsfmvtty1CzEkCAeCR-d5TYfkg@mail.gmail.com>
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
>>
>
>
next prev parent reply other threads:[~2014-08-14 1:14 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-12 14:29 reading mail with emacs visaris tds.net
2014-08-12 17:14 ` Sharon Kimble
2014-08-13 1:18 ` Robert Thorpe
[not found] ` <CA+Jy_pASyaNiFxAoNF-+P0fhpsfmvtty1CzEkCAeCR-d5TYfkg@mail.gmail.com>
2014-08-14 1:14 ` visaris tds.net [this message]
2014-08-14 1:26 ` visaris tds.net
[not found] ` <mailman.7089.1407979619.1147.help-gnu-emacs@gnu.org>
2014-08-14 23:52 ` Emanuel Berg
2014-08-15 4:09 ` Jorge Araya Navarro
[not found] ` <mailman.7112.1408075888.1147.help-gnu-emacs@gnu.org>
2014-08-15 19:19 ` Emanuel Berg
[not found] <mailman.7024.1407858485.1147.help-gnu-emacs@gnu.org>
2014-08-12 16:57 ` Emanuel Berg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CA+Jy_pCCs2=fqA9jVjc9OqQrrmXFOxxtiHA+=-+YGJVrqL80nA@mail.gmail.com' \
--to=visaris@tds.net \
--cc=help-gnu-emacs@gnu.org \
--cc=rt@robertthorpeconsulting.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.