forwarder d'email


Le principe de ce petit programme est de prendre tous les messages d'un compte POP et de les renvoyer vers une autre adresse.

l'option '-d' passée en ligne de commande permet de supprimer les mails du compte pop.
Il y a donc pas mal de paramètres à passer:
  • smtp_name: nom du serveur smtp
  • smtp_from: ne sert pas a grand chose, mais c'est indispensable, vous pouvez mettre ici votre adresse sur le compte pop
  • smtp_to: l'adresse a laquelle vous voulez faire suivre les mails récupérer
  • pop_name: le nom du serveur pop3
  • user: votre nom d'utilisateur sur le serveur pop3
  • pass: le mot de passe qui va avec


#include <arpa/telnet.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define PACKET_SIZE  1024

#define DEBUG 1

void appli ( void ) ;
int writen(int fd, char *ptr, int n);
int readn(int fd, char *ptr, int n);

char *smtp_name = "SMTP SERVER";
unsigned short smtp_port = 25;
char smtp_from[] = "mail from: <ADDRESSE DE L ENVOYEUR>\n";
char smtp_to[] = "rcpt to: <ADDRESSE DESTINATAIRE>\n";

char *pop_name = "SERVER POP";
int pop_port = 110;
char *user= "USERNAME POP";
char *pass= "PASSWORD";

int delete_msg = 0;

int to_pop_socket = -1;
int to_smtp_socket = -1;

int main (int argc, char *argv[])
{
struct sockaddr_in popSockAddr;    /* addresse de la socket */
struct hostent *popHostEnt;        /* description du host serveur */
unsigned long popAddr;                       /* addr du serveur */

struct sockaddr_in smtpSockAddr;    /* addresse de la socket */
struct hostent *smtpHostEnt;        /* description du host serveur */
unsigned long smtpAddr;                       /* addr du serveur */

long status;
char buffer[PACKET_SIZE+1];
int optval = 1;

  if ( argc == 2 )
    if ( ! strncmp(argv[1], "-d", 2) )
      delete_msg = 1;


  bzero(&popSockAddr,sizeof(popSockAddr));/*init a zero popSockAddr*/
  popAddr = inet_addr(pop_name); /* converti l'adress ip 9.100.1.1 
                                       en entier long */
  bzero(&smtpSockAddr,sizeof(smtpSockAddr));
  smtpAddr = inet_addr(smtp_name);

  if ( (long)popAddr != (long)-1)
          bcopy(&popAddr,&popSockAddr.sin_addr,sizeof(popAddr));
  else                           /* si on a donne un nom  */
  {
     popHostEnt = gethostbyname(pop_name);
     if (popHostEnt == NULL)
     {
             printf("ca chie gethost\n");
             exit(0);
     }
     bcopy(popHostEnt->h_addr,&popSockAddr.sin_addr,popHostEnt->h_length);
  }

  if ( (long)smtpAddr != (long)-1)
          bcopy(&smtpAddr,&smtpSockAddr.sin_addr,sizeof(smtpAddr));
  else                           /* si on a donne un nom  */
  {
     smtpHostEnt = gethostbyname(smtp_name);
     if (smtpHostEnt == NULL)
     {
             printf("ca chie gethost\n");
             exit(0);
     }
     bcopy(smtpHostEnt->h_addr,&smtpSockAddr.sin_addr,smtpHostEnt->h_length);
  }


  popSockAddr.sin_port = htons(pop_port); /* host to network port  */
  popSockAddr.sin_family = AF_INET;  /* AF_*** : INET=internet */
  /* creation de la socket */

  smtpSockAddr.sin_port = htons(smtp_port); /* host to network port  */
  smtpSockAddr.sin_family = AF_INET;  /* AF_*** : INET=internet */
  /* creation de la socket */

  if ( (to_pop_socket = socket(AF_INET,SOCK_STREAM,0)) < 0)
  {
          printf("ca chie creation socket client\n");
          exit(0);
  }
  if ( (to_smtp_socket = socket(AF_INET,SOCK_STREAM,0)) < 0)
  {
          printf("ca chie creation socket client\n");
          exit(0);
  }
/*
  if (setsockopt(to_pop_socket,SOL_SOCKET,SO_KEEPALIVE,
      (char *)&optval,sizeof(int))                           <0)
  {
          printf("ca chie setsockopt\n");
          exit(0);
  }
*/
  /* requete de connexion */
  if(connect(to_pop_socket,(struct sockaddr *)&popSockAddr,
             sizeof(popSockAddr))<0)
  {
          printf("ca chie demande de connection\n");
          exit(0);
  }
  if(connect(to_smtp_socket,(struct sockaddr *)&smtpSockAddr,
             sizeof(smtpSockAddr))<0)
  {
          printf("ca chie demande de connection\n");
          exit(0);
  }
  appli();

  /* fermeture de la connection */
  shutdown(to_pop_socket,2);
  close(to_pop_socket);
  shutdown(to_smtp_socket,2);
  close(to_smtp_socket);
  return 0;
}


int writen(int fd, char *ptr, int n)
{
char *p;
int nl, nw;
        nl = n;
        while ( nl > 0 ) {
                nw = write(fd, ptr, nl);
                if ( nw <= 0 )
                        return nw;     /*error*/
                nl -= nw;
                ptr += nw;
        }
        return (n-nl);
}

int readn(int fd, char *ptr, int n){
int nl, nr, retry=0;

        nl = n;
        bzero(ptr,n);
        while ( nl > 0 ) {
                nr = read(fd,ptr,nl);
                if (nr < 0 ) {
                    if (errno != EAGAIN) { printf("EAGAIN\n"); exit(1); }
                    retry++;
                    usleep(100);
                    if ( retry >= 5 ) return nr;     /*error*/
                } else {
                    if ( nr == 0 )
                           break;
                }
                nl -= nr;
                ptr += nr;
                if ( *(ptr-2) == '\r' && *(ptr-1) == '\n' )
                  break;
        }
        *ptr = 0x00;
        return (n-nl);
}

int test_OK(char *buf, int do_exit) {
 char *ptr, tmp[PACKET_SIZE+1];

    bzero(tmp, PACKET_SIZE+1);
    if ((ptr=strstr(buf, "+OK")) == NULL) {
      if (DEBUG) printf("%s", buf);
        if ( strstr(buf, "-ERR") ) {
          printf("ERROR: -->%s<--\n", buf);
          exit(1);
        }
      if (do_exit ) exit(1);
      else return 1;
    } else {
      if (DEBUG) printf("-->%s<--\n",ptr);
      while(*ptr != '\n') ptr++ ;
      bcopy(ptr+1,tmp,strlen(ptr));
      bzero(buf,PACKET_SIZE+1);
      bcopy(tmp, buf, strlen(tmp));
    }
    return 0;
}

int test_250(char *buf) {
 char *ptr, tmp[PACKET_SIZE+1];

    bzero(tmp, PACKET_SIZE+1);
    if ((ptr=strstr(buf, "250 OK")) == NULL) {
      if (DEBUG) printf("ERROR: %s", buf);
      exit(1);
    } else {
      if (DEBUG) printf("-->%s<--\n",ptr);
      while(*ptr != '\n') ptr++ ;
      bcopy(ptr+1,tmp,strlen(ptr));
      bzero(buf,PACKET_SIZE+1);
      bcopy(tmp, buf, strlen(tmp));
    }
    return 0;
}

void begin_smtp( void ) {
char buf[PACKET_SIZE+1];
  readn(to_smtp_socket,buf,PACKET_SIZE);
  printf(buf);

}

void begin_mail( void ) {
char buf[PACKET_SIZE+1];
sleep(1);
  writen(to_smtp_socket,smtp_from,strlen(smtp_from));
  printf(smtp_from);
  readn(to_smtp_socket,buf,PACKET_SIZE);
  test_250(buf);
  writen(to_smtp_socket,smtp_to,strlen(smtp_to));
  printf(smtp_to);
  readn(to_smtp_socket,buf,PACKET_SIZE);
  test_250(buf);
  writen(to_smtp_socket,"data\n",6);
  printf(buf);
  readn(to_smtp_socket,buf,PACKET_SIZE);
  printf(buf);
}

void appli ( void )
{
unsigned char bufw[PACKET_SIZE+1];
unsigned char bufr[PACKET_SIZE+1];
unsigned char list[PACKET_SIZE+1];
int n, msg, index, retry = 4;

  begin_smtp();

  bzero(bufw, PACKET_SIZE+1);
  bzero(bufr, PACKET_SIZE+1);

  do {
    n=readn(to_pop_socket,bufr,PACKET_SIZE);
    retry--;
  } while(test_OK(bufr,retry==0));

  //if (strlen(bufr) == 0 ) n=readn(to_pop_socket,bufr,PACKET_SIZE);
  if (DEBUG) printf("??? %s ???\n", bufr);
  sprintf(bufw,"USER %s\r\n",user);
  writen(to_pop_socket,bufw,strlen(bufw));
  n=readn(to_pop_socket,bufr,PACKET_SIZE);
  if (DEBUG) printf("USER: ");
  test_OK(bufr,1);

  sprintf(bufw,"PASS %s\r\n",pass);
  writen(to_pop_socket,bufw,strlen(bufw));
  n=readn(to_pop_socket,bufr,PACKET_SIZE);
  if (DEBUG) printf("PASS: ");
  test_OK(bufr,1);

  sprintf(bufw,"LIST\r\n");
  writen(to_pop_socket,bufw,strlen(bufw));
  n=readn(to_pop_socket,bufr,PACKET_SIZE);
  if (DEBUG) printf("LIST: ");
  test_OK(bufr,1);

  if (strlen(bufr) == 0 ) n=readn(to_pop_socket,list,PACKET_SIZE);
  else bcopy(bufr, list, strlen(bufr) + 1) ;
  if (DEBUG) printf(list);

  index = 0;
  while ( list[index] != '.' ) {

    sscanf(&list[index], "%d", &msg);
    while(list[index++] != '\n');

    sprintf(bufw,"RETR %d\r\n",msg);
    if (DEBUG) printf("^[[34m %s^[[30m",bufw);

    begin_mail();

    writen(to_pop_socket,bufw,strlen(bufw));
    n=readn(to_pop_socket,bufr,PACKET_SIZE);
    test_OK(bufr,1);

    n=strlen(bufr);
    do {
      if (strlen(bufr) == 0 ) n=readn(to_pop_socket,bufr, PACKET_SIZE);
      writen(to_smtp_socket, bufr, n);
      if ( ! strncmp("\r\n.\r\n",&bufr[n-5],5) ) break;
      bzero(bufr, PACKET_SIZE+1);
    } while ( 1 );

    readn(to_smtp_socket,bufr, PACKET_SIZE);
    test_250(bufr);

    if ( delete_msg ) {
      sprintf(bufw,"DELE %d\r\n",msg);
      if (DEBUG) printf("^[[34m %s^[[30m",bufw);
      writen(to_pop_socket,bufw,strlen(bufw));
      n=readn(to_pop_socket,bufr,PACKET_SIZE);
      test_OK(bufr,1);
    }
  }

  sprintf(bufw,"QUIT\r\n");
  writen(to_pop_socket,bufw,strlen(bufw));
  n=readn(to_pop_socket,bufr,PACKET_SIZE);
  test_OK(bufr,0);

}