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;
};
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.