[win32][c][dev-c++] anomail envoie smtp simple

Description

Bonjours à tous, bon voilà une petite source suite à une question du forum,

- Recodage d'une partie de l'application, correction d'un bug avec les pièces jointes :)

- ajout de nouvelles fonctionnalités ^^:
  • double clic sur un élément de la liste d'information, permet de voir en popup le contenu complet de l'élément
  • ajout de la gestion ESMTP (information lors de la connexion pour connaitre les commandes standards)
  • gestion d'historique
  • TEST RELAIS : permet d'effectuer un tests d'envoi, tout les trames de message sont envoyés mis à part le quit de validation final.
  • ENVOI MULTIPLE : permet l'envoie de plusieurs messages identiques
  • PJ COORDONNEES : permet l'envoie dans la cas d'envoie multiple des pièces jointes une par une avec les duplicatas de messages


Reste à ajouter:
  • gestion de multiples destinataires
  • login + mdp de connexion
  • enlever les fopen et tout passer en win32
  • synchronisation pour l'historique en cas d'utilisation multi threads


si vous avez des remarques n'hésitez pas :)

Source / Exemple :


//------------------------------------------------------------------------------
// Projet AnoMails      : Envoie de Mails + pièce jointe + possibilité anonyme
// Auteur               : Hanteville Nicolas
// Fichier              : Mail.c
// Version              : 0.3.6
// Date de modification : 28/02/2008
// Procédure de gestion d'envoie de fichiers + envoie de mails
//------------------------------------------------------------------------------
#include "ressources.h"
//------------------------------------------------------------------------------
//envoyer une pièce jointe
// i = num d'item de la liste view, htmp = handle du listeview, 
//HChargement= handle de la barre de chargement
// sock = socket
//------------------------------------------------------------------------------
void envoyerPs(unsigned short i,HANDLE htmp,HANDLE HChargement,SOCKET sock)
{
    char buffer[TEM];  // Variables temporaires
    char tmp[TAILLE_TMP];
    char *tmpfic;
    long int taille_fichier;//nb octets 
    FILE *source;
    
     //récupération de l'emplacement du fichier
     ListView_GetItemText(htmp,i,1,buffer,TEM);
     AjouterItemInfos(ETAT_OK_INFO,buffer);                               

  // convertion base 64
     if ((source= fopen(buffer,"rb"))!=NULL)//ouverture du fichier test
     {
       //ajout entête
           //récupération du nom de fichier
           ListView_GetItemText(htmp,i,0,tmp,TAILLE_TMP);
         
           sprintf(buffer,"\r\n--__SPACE\r\nContent-Type: application/x-msdownload; name=\"%s\"\r\n"
                        "Content-Transfer-Encoding: base64\r\n"
                        "Content-Disposition: attachment; filename=\"%s\"\r\n\r\n",tmp,tmp);      

           EnvoieCommande(ETAT_NORECEIVE,sock,buffer,strlen(buffer));
       
           //calcul de la taille du fichier
           fseek(source, 0, SEEK_END);// on se place a la fin du fichier
           taille_fichier = ftell(source);// nombre d'octet ou place dans le fichier = taille
           
           sprintf(buffer,"Taille du fichier <%s> %u octets",tmp,taille_fichier);
           AjouterItemInfos(ETAT_OK_INFO,buffer);

           if (taille_fichier>0)
           {
             fseek(source, 0, SEEK_SET);// on se replace au debut
             tmpfic = malloc(taille_fichier+1); // on instance la mémoire avec la taille du fichier
             
             //récupération du comptenu du fichier
             fread(tmpfic,1, taille_fichier, source);                

             //params : comptenue fichier + socket + taille du fichier
             DecoupeTrame(tmpfic,sock,taille_fichier);// gere envoie + codage base 64
             free(tmpfic);
           }else
           {
             sprintf(buffer,"Erreur: fichier \"%s\"de taille 0 octet!!!",tmp);
             AjouterItemInfos(ETAT_NOK_RETURN,buffer);
           }
           fclose(source);
     }else
       AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: fichier introuvable!!!");

     SendMessage(HChargement, PBM_SETPOS, (WPARAM)(i*80)/NB_PieceJointes, 0);
}

//------------------------------------------------------------------------------
//Enregistrer les informations passees
//------------------------------------------------------------------------------
void CompteRendu()
{
  //variables
  char var[TAILLE_MAX];
  int NBLigne=0;
  int ligne;
  DWORD copiee;
  HWND hListView = GetDlgItem(HGeneral,LST_INFO);
  // on récupère le nombre de lignes
  NBLigne=ListView_GetItemCount(hListView);
  
  //ouverture du fichier et écriture à la suite
  HANDLE HLog = CreateFile(NOMFICLOG,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_ALWAYS,FILE_FLAG_SEQUENTIAL_SCAN,0);

  if (HLog == INVALID_HANDLE_VALUE || NBLigne==0)
  {
   AjouterItemInfos(ETAT_NOK_RETURN,"ERREUR - création de rapport impossible !!!");
   CloseHandle(HLog);
   return;
  }  
  
  //on se place à la fin du fichier
  SetFilePointer(HLog,GetFileSize(HLog,NULL),0,FILE_BEGIN);  
   
  WriteFile(HLog,"|-------------------------------------------------------------------------------------------------------------------------------------|\r\n",137,&copiee,0);  
  // on récupère les items un par un , par ligne et on les met dans une variable ligne puis écriture
  for (ligne=NBLigne-1;ligne;ligne--)
  {
    // colonne 1 = 23 caractères
    ListView_GetItemText(hListView,ligne,0,var,TAILLE_MAX);
    WriteFile(HLog,var,strlen(var),&copiee,0);
    ListView_GetItemText(hListView,ligne,1,var,TAILLE_MAX);
    WriteFile(HLog,var,strlen(var),&copiee,0);    
    WriteFile(HLog,"\r\n",2,&copiee,0);
  }  
  
  WriteFile(HLog,"|-------------------------------------------------------------------------------------------------------------------------------------|\r\n",137,&copiee,0);   
  CloseHandle(HLog);
  AjouterItemInfos(ETAT_OK_INFO,"Ajout au rapport OK!");
}
//------------------------------------------------------------------------------
//activer désactiver composants 
//------------------------------------------------------------------------------
void ActiveSys(BOOL etat)
{
    EnableWindow(GetDlgItem(HGeneral,CB_PROFIL),etat); 
    EnableWindow(GetDlgItem(HGeneral,CB_SERVEUR),etat);
    
    EnableWindow(GetDlgItem(HGeneral,BT_PIECES_JOINTES),etat);
    
    EnableWindow(GetDlgItem(HGeneral,EDIT_NOM_EXP),etat);
    EnableWindow(GetDlgItem(HGeneral,EDIT_EXPEDITEUR),etat);
    EnableWindow(GetDlgItem(HGeneral,EDIT_DESTINATAIRE),etat);
    EnableWindow(GetDlgItem(HGeneral,EDIT_SUJET),etat);
    EnableWindow(GetDlgItem(HGeneral,EDIT_MSG),etat);
    EnableWindow(GetDlgItem(HGeneral,EDIT_PORT),etat);
    
    EnableWindow(GetDlgItem(HGeneral,BT_ENVOYER),etat);
    
    EnableWindow(GetDlgItem(HGeneral,BT_MULTIPLE_CP),etat);

    EnableWindow(GetDlgItem(HGeneral,BT_REP),etat?ACTIVE_HISTORIQUE:FALSE);
    
    EnableWindow(GetDlgItem(HGeneral,BT_REP),etat?ACTIVE_HISTORIQUE:FALSE);
    
    ShowWindow(HPiecJointe,etat && PiecJointe_Visible?SW_SHOW:SW_HIDE);
    
}
//------------------------------------------------------------------------------
//ajouterItem au infos
// etat informe = TRUE = envoi, FALSE retour  , -1 = <>, -2 : ##
//------------------------------------------------------------------------------
void AjouterItemInfos(short etat,char *chaine)
{
        LVITEM lvi;
        HANDLE htmp = GetDlgItem(HGeneral,LST_INFO);
        
        //ajout d'un item
        lvi.mask = LVIF_TEXT|LVIF_PARAM;
        lvi.iSubItem = 0;
        lvi.lParam = LVM_SORTITEMS;
        lvi.pszText="";
        lvi.iItem = nb++;
        
        nb=ListView_InsertItem(htmp, &lvi);
        
        //infos
        ListView_SetItemText(htmp,nb,1,chaine);
        
        //état
        switch(etat)
        {
          case ETAT_OK_SEND: ListView_SetItemText(htmp,nb,0,"-->>"); break;
          case ETAT_OK_RETURN: ListView_SetItemText(htmp,nb,0,"<<--"); break;
          case ETAT_OK_INFO: ListView_SetItemText(htmp,nb,0,"-<>-"); break;
          case ETAT_NOK_RETURN: ListView_SetItemText(htmp,nb,0,"###"); break;
        }
}
//------------------------------------------------------------------------------
// fonction on indique le socket et la commande a envoyé
//------------------------------------------------------------------------------
BOOL EnvoieCommande(BOOL recive,SOCKET sock,char *commande,int tailleCmd)
{
   char tmp[TAILLE_TAMPON+33];//33 = entête
   char recue[TAILLE_TAMPON];
   unsigned short i;
   
   ZeroMemory(recue, TAILLE_TAMPON-1);
 //  Sleep( TEMP_ATTENTE );
   
   send( sock, commande,tailleCmd, 0 );   
   
   sprintf(tmp,"Envoye: %s",commande);
   AjouterItemInfos(ETAT_OK_SEND,tmp);

   if (recive==ETAT_RECEIVE)
   {
       recv( sock, recue, TAILLE_TAMPON, 0 );
       if ((recue[0]=='\0')||(recue[0]=='5'))
       {   
           sprintf(tmp,"Recue: ERREUR DE CONNEXION : %s !!",recue);
           AjouterItemInfos(ETAT_NOK_RETURN,tmp);
           return 1;
       }
       else
       {
           sprintf(tmp,"Recue: %s",recue);
           AjouterItemInfos(ETAT_OK_RETURN,tmp);
       }
  };
 return 0;
};

//------------------------------------------------------------------------------
// procédure d'envoie du mail barbar
//------------------------------------------------------------------------------
DWORD  WINAPI EnvoyMultiplesMails(LPVOID lParam)
{
       
  unsigned int boucle = 1,k=0;
  char tmp[5];   //9999 maximum       

  GetWindowText(GetDlgItem(HGeneral,EDIT_NB_ENVOI), tmp, TAILLE_TMP);
  if (tmp[0]) boucle = atoi(tmp);

  for (k=0;k<boucle;k++)
  {
    EnvoyMail(k);
    //CreateThread(NULL,0,EnvoyMail,k,0,0);
  }

  /*while (boucle--)
  {
    EnvoyMail(0);
    _sleep(200);
  }*/
}

//------------------------------------------------------------------------------
// procédure d'envoie du mail
//------------------------------------------------------------------------------
DWORD  WINAPI EnvoyMail(LPVOID lParam)
{
 //variables réseau:    
    WSADATA wsaData;//variable pour initialisé la connexion
    SOCKET sock; // notre socket qui va permettre la communication
    SOCKADDR_IN sinfo; // la configuration du socket   
    char buffer[TEM];  // Variables temporaires
    unsigned short i=lParam;  
    DWORD copiee; 
    unsigned int MyPort=0;
    BOOL Mres=1;
    char Ztmp[TAILLE_MAX];
    HANDLE htmp,HChargement;
    
    // gestion base 64
    FILE *source;
    char *tmpfic;
    long int taille_fichier;//nb octets  

    //on masque les boutons
    ActiveSys(0);

    //init
    HChargement = GetDlgItem(HGeneral,BAR_CHARGEMENT);
    SendMessage(HChargement, PBM_SETPOS, (WPARAM)0, 0);     
    
    //vider listview
    SendMessage(GetDlgItem(HGeneral,LST_INFO),LVM_DELETEALLITEMS,0,0); 
    nb = 0;                       
 
   // on init la connexion si sa fonctionne on continue
   if (!WSAStartup(0x0101,&wsaData))// si pas d'erreur
   {
        sock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
         
       // on récupère l'IP
         GetWindowText(GetDlgItem(HGeneral,CB_SERVEUR), buffer, TAILLE_TMP);
         if (buffer[0] == 0)
         {
           WSACleanup();// on libère le socket 
           //message d'erreur
           MessageBox(0, "Vous devez indiquer un serveur SMTP!!","Erreur", MB_ICONEXCLAMATION|MB_SYSTEMMODAL);
           ActiveSys(1);
           return 0;
         }
               
        // ici on vérifi si c'est une IP ou un nom
        if ((buffer[0]>47)&&(buffer[0]<58)) 
        {
            sinfo.sin_addr.s_addr = inet_addr(buffer);	// @IP Socket = @IP Serveur
            sprintf(Ztmp,"Etat: Connexion a IP (direct): %s",buffer);
            AjouterItemInfos(ETAT_OK_INFO,Ztmp);
        }else
        {
           struct hostent *host; 
            
           if (host=gethostbyname(buffer))
           {
                struct in_addr **a; 
                a=(struct in_addr **)host->h_addr_list;
                
                sprintf(Ztmp,"Etat: Connexion IP (resolution DNS OK): %s (IP:%s)",buffer,inet_ntoa(**a));               
                AjouterItemInfos(ETAT_OK_INFO,Ztmp);
                sinfo.sin_addr.s_addr=inet_addr(inet_ntoa(**a));
           }else
           {
             AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: RESOLUTION DNS IMPOSSIBLE!!!");
           
             //on quitte
              WSACleanup();// on libère le socket  
             
             //message d'erreur
             MessageBox(0, "Résolution de nom du serveur SMTP impossible!!!","Erreur", MB_ICONEXCLAMATION|MB_SYSTEMMODAL);
             ActiveSys(1);
             return 0;
           }
         }        
         //progression
         SendMessage(HChargement, PBM_SETPOS, (WPARAM)5, 0);
  
         //init de la connexion réseau
         buffer[0]=0;
         GetWindowText(GetDlgItem(HGeneral,EDIT_PORT), buffer, TAILLE_TMP);
         if (buffer[0]) MyPort = atoi(buffer);
         
           if (MyPort>0 && MyPort<65535)
             sinfo.sin_port = htons(MyPort);// Port du Socket Serveur 
           else
           {
             SetWindowText(GetDlgItem(HGeneral,EDIT_PORT),"25");
             sinfo.sin_port = htons(PORT);// Port du Socket Serveur 
           }
       	   sinfo.sin_family = AF_INET;				// Protocole internet    
                       
         	 // DEMANDE DE CONNECTION AU SERVEUR
         	   if (!connect(sock,(SOCKADDR *)&sinfo,sizeof(sinfo)))	// Demande de Connection au Serveur      
             {       
               AjouterItemInfos(ETAT_OK_INFO,"Etat: Connexion au serveur OK");
               
               //recupération des infos lors de la connexion
               buffer[0]=0;
               recv( sock, buffer, TAILLE_TAMPON, 0 );
               
               snprintf(Ztmp,TAILLE_MAX,"Recue: %s",buffer);    
               AjouterItemInfos(ETAT_OK_RETURN,Ztmp);  

               //test EHLO 
               if(EnvoieCommande(ETAT_RECEIVE,sock,"EHLO smtp.go.mail.com\r\n",23))
               {
                 AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: EHLO NON ACCEPTE!!!");
                 if(EnvoieCommande(ETAT_RECEIVE,sock,"HELO smtp.go.mail.com\r\n",23))Mres=0;
               }
               if (Mres)
               {
    //MAIL FROM:
                   GetWindowText(GetDlgItem(HGeneral,EDIT_EXPEDITEUR), Ztmp, TAILLE_TMP);
                   sprintf(buffer,"MAIL FROM: <%s>\r\n",Ztmp);
                   
                   if(!EnvoieCommande(ETAT_RECEIVE,sock,buffer,strlen(buffer)))
                   {     
    //RCPT TO:
                        GetWindowText(GetDlgItem(HGeneral,EDIT_DESTINATAIRE), Ztmp, TAILLE_TMP); 
                        sprintf(buffer,"RCPT TO: <%s>\r\n",Ztmp);
                         
                        if(!EnvoieCommande(ETAT_RECEIVE,sock,buffer,strlen(buffer)))               
                        {
    //DATA                        
                             if(!EnvoieCommande(ETAT_RECEIVE,sock,"DATA\r\n",6))
                             {
                               //corps avec infos sur de qui sa viens
                               //from
                               GetWindowText(GetDlgItem(HGeneral,EDIT_EXPEDITEUR), Ztmp, TAILLE_TMP); //mail
                               sprintf(buffer,"From: %s <",Ztmp);
                               GetWindowText(GetDlgItem(HGeneral,EDIT_NOM_EXP), Ztmp, TAILLE_TMP); //nom
                               strcat(buffer,Ztmp);
                               strcat(buffer,">\r\n\0");
    
                               if(EnvoieCommande(ETAT_NORECEIVE,sock,buffer,strlen(buffer)))
                                 AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: CORPS <from:> NON ACCEPTE!!!");
    
                               //to
                               GetWindowText(GetDlgItem(HGeneral,EDIT_DESTINATAIRE), Ztmp, TAILLE_TMP);
                               sprintf(buffer,"To: <%s>\r\n",Ztmp);

                               if(EnvoieCommande(ETAT_NORECEIVE,sock,buffer,strlen(buffer)))
                                 AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: CORPS <to:> NON ACCEPTE!!!");
                               
                               //sujet
                               GetWindowText(GetDlgItem(HGeneral,EDIT_SUJET), Ztmp, TAILLE_TMP);
                               sprintf(buffer,"Subject: %s\r\n",Ztmp);
                                                      
                               if(EnvoieCommande(ETAT_NORECEIVE,sock,buffer,strlen(buffer)))
                                 AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: CORPS <subject:> NON ACCEPTE!!!");
                               
                               //progression
                               SendMessage(HChargement, PBM_SETPOS, (WPARAM)10, 0);
                               
                               //gestion des objects + texte du message
                               if (NB_PieceJointes)
                               {
                                 strcpy(buffer,"MIME-Version: 1.0\r\nContent-Type: multipart/mixed; boundary=\"__SPACE\"\r\n\r\n"
                                               "--__SPACE\r\nContent-type: text/plain; charset=ISO-8859-1;\r\n\r\n");                                    
                                 
                                 EnvoieCommande(ETAT_NORECEIVE,sock,buffer,strlen(buffer));                                         
                                 //corps
                                 GetWindowText(GetDlgItem(HGeneral,EDIT_MSG), buffer, TEM);
  
                                 EnvoieCommande(ETAT_NORECEIVE,sock,buffer,strlen(buffer));                                                         
                               
                                 //récupération d'un handle sur le liste view
                                 htmp = GetDlgItem(HPiecJointe,LST_GPJ);
                                 
                                 //fichiers
                                 if (ACTIVE_PJ_COORDONNEES)
                                 {
                                   if (i<NB_PieceJointes) envoyerPs(i,htmp,HChargement,sock);
                                 }else
                                 {
                                   for (i=0;i<NB_PieceJointes;i++)
                                   {
                                     envoyerPs(i,htmp,HChargement,sock);
                                   }
                                 }
                                 
                                 EnvoieCommande(ETAT_NORECEIVE,sock,"\r\n--__SPACE\r\n",13);
                               }else //pas d'object
                               {
                                EnvoieCommande(ETAT_NORECEIVE,sock,"\r\n",2);
                                GetWindowText(GetDlgItem(HGeneral,EDIT_MSG), buffer, TEM);
                                EnvoieCommande(ETAT_NORECEIVE,sock,buffer,strlen(buffer));
                               }
    
                               if (!ACTIVE_TEST)
                               {
                                 // find du message
                                 if(!EnvoieCommande(ETAT_RECEIVE,sock,"\r\n.\r\n",5)) //fin du message
                                    EnvoieCommande(ETAT_RECEIVE,sock,"QUIT\r\n",6); //fin de communication  
                               }else AjouterItemInfos(ETAT_OK_INFO,"Attention: Relaying possible!!!");
   
                               //progression
                               SendMessage(HChargement, PBM_SETPOS, (WPARAM)100, 0);   
                               
                               if (ACTIVE_EDIT_NB_ENVOI == 0)
                               MessageBox(0,"Message envoyé!!!","Informations",MB_OK|MB_TOPMOST|MB_ICONEXCLAMATION);
                               
                             }else
                               AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: MESSAGE <DATA> NON ACCEPTE!!!");
                        }else
                          AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: MESSAGE <RCPT TO> NON ACCEPTE!!!");
                   }else
                     AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: MESSAGE <MAIL FROM> NON ACCEPTE!!!");
                 }else
                   AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: DIALOGUE AVEC LE SERVEUR REFUSE!!!");
                   AjouterItemInfos(ETAT_OK_INFO,"Etat: Déconnexion du serveur OK"); 
             }else
               AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: CONNEXION AU SERVEUR REFUSEE!!!");
       }else
         AjouterItemInfos(ETAT_NOK_RETURN,"Erreur: INITIALISATION WSADATA IMPOSSIBLE!!!");
       
      // on réinit la connexion pour utilisation antérieur
      shutdown(sock,2);
      closesocket(sock);//liberation du socket 
      WSACleanup();// on libère le socket  
      
      if (ACTIVE_HISTORIQUE)CompteRendu();
      
      //progression
      //Sleep(100);
      SendMessage(HChargement, PBM_SETPOS, (WPARAM)0, 0);  
      
      //on affiche les boutons
      ActiveSys(1);
      
      return 0;     
};

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.