[c/linux] envoyer un message par mail

Soyez le premier à donner votre avis sur cette source.

Vue 29 062 fois - Téléchargée 1 067 fois

Description

C'est fait de la manière la plus simple qui soit,
avec un minimum de variables déclarées.

Si quelqu'un s' attend à un client mail complet, qu'il passe son chemin
ou qu'il en installe un! Pour les autres, ce code constituera l' ossature
d'une application. C'est une des raisons pour lesquelles je le poste.
L' autre raison étant bien entendu de présenter brièvement le protocole SMTP
à ceux qui s'y intéressent.

A vous de l' étoffer en déclarant 60 variables, pour le FROM, le TO, etc...
Parce qu'il faut bien reconnaitre que tout est en dur!

Aussi, le code est du C -toujours par souci de flexibilité- pour
sa facilité de passage vers le C++. Qui peut le moins peut le plus.

Source / Exemple :


// Envoyer un mail
// gcc -Wall -o mail mail.c

#include <stdio.h>	// pour puts()
#include <string.h>	// pour bzero() bcopy() strlen()

//includes réseau
#include <unistd.h>	// pour close()
#include <netdb.h>	// pour gethostbyname()
#include <arpa/inet.h>  // pour sockaddr_in

int sk = -1;		//le descripteur du socket

char serveur[] = "smtp.wanadoo.fr";

char lemail[] = "HELO wanadoo.fr\r\n"
		"MAIL FROM: <blabla@orange.fr>\n"
		"RCPT TO: <truc@truc.fr>\n"
		"DATA\r\n"
		"Subject: le mur et les oreilles\r\n"
 		"FROM: François <blabla@orange.fr>\r\n"
		"TO: Segolene <truc@unautre.fr>\r\n"
		"Bijour\r\n"
		"petit message\r\n"
		".\r\n"
		"QUIT\r\n\r\n";

//Déclaration des Prototypes de fonctions
unsigned short init_socket();
void recevoir_reponse();

int main (int argc, char *argv[])
{

	if (init_socket())
	{
	send(sk, lemail, strlen(lemail)-1, 0);
	recevoir_reponse(); //fermera le socket.
	}

	return 0;
}

unsigned short init_socket()
{
	struct sockaddr_in serveurSockAddr;	// addresse
	struct hostent *serveurHostEnt;		// description host serveur
	unsigned long hostAddr;			// addr du serveur

	bzero(&serveurSockAddr,sizeof(serveurSockAddr));
	hostAddr = inet_addr(serveur); // convertit l'adresse ip en entier long

	if ( (long)hostAddr != (long)-1)
		bcopy(&hostAddr,&serveurSockAddr.sin_addr,sizeof(hostAddr));
	else  // on a donné un nom, pas une IP
	{
 		serveurHostEnt = gethostbyname(serveur);
		if (serveurHostEnt == NULL)
  		{
			puts("probleme gethost");
			return 0;
		}
 		bcopy(serveurHostEnt->h_addr,&serveurSockAddr.sin_addr, serveurHostEnt->h_length);
	}

	serveurSockAddr.sin_port = htons(25); //port 25 pour SMTP
	serveurSockAddr.sin_family = AF_INET;

	if ( (sk = socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
		puts("Impossible de creer le socket");
		return 0;
 	}

	if(connect(sk,(struct sockaddr *)&serveurSockAddr, sizeof(serveurSockAddr)) < 0)
	{
		puts("probleme sur connect()");
		return 0;
	}
	else
	{
		printf("Connecté au serveur %s\n",serveur);
		return 1;
	}
}

void recevoir_reponse()
{
	puts("En attente de la reponse ...\n");
	char  tempBuffer[1024];
	int retval;

	while(1)
	{
	    retval = recv(sk, tempBuffer, sizeof(tempBuffer)-1, 0);
	    if (retval==0)
	    { 
			shutdown(sk,2); //ferme le socket
			close(sk);
			puts("Socket fermé.");
	        break;
	    }
	    else if (retval == -1)
	    {
	        puts("Erreur pendant la reception");
	    }
	    else
	    {
	        tempBuffer[retval] = 0;
	        puts(tempBuffer);
	    }
	}
}

Conclusion :


Note pour les nouveaux Linuxiens:

Pour compiler "à la main" dans une console c'est:
$ cd repertoire
$ gcc -Wall -o mail mail.c

Puis pour exécuter le prog c'est:
$ ./mail
En sachant que double-cliquer sur l' exécutable marche aussi.

Note2: si vous avez des problèmes avec les accents dans la console, faut voir
si vos "Locales" sont bien configurées pour le français.

La conversion vers le Win32 est ultra simple, je modifie le code
à cet effet si quelqu'un le demande. Deux ou trois directives pré-processeur
et le binz devient portable à 100%, sans danser la java. De toute façon Java
est écrit en langage C ...

Le main() appelle 2 routines:
- init_socket() qui crée un socket et se connecte sur le port 25,
- recevoir_reponse() qui lit les paquets entrants et les affiche sur la sortie standard.

Il n' y a effectivement pas de conversation protocolaire entre le client et le serveur,
puisque le prog envoie un string complet au serveur sans écouter ce que lui répond le
serveur, à la manière d'une requête HTTP! C'est du brut, du simple et du pas compliqué.

J'espère que vous apprécierez.

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
466
Date d'inscription
mercredi 12 août 2009
Statut
Membre
Dernière intervention
17 octobre 2011

Salut, très bon code !
Par contre quand tout mes mails envoyé son pas valide et vont en indésirable : comment rectifier le problème ? Header ? Possible avec ton code ?

Ps: sous windows windows.h n'est pas nécessaire pour manipuler, on l'utilise pour les thread mais la lib pthread est préférable puisqu'elle multiplate-form ( Windows & Linux : rien à foutre de Mac )

++
Messages postés
571
Date d'inscription
vendredi 30 décembre 2005
Statut
Membre
Dernière intervention
12 juillet 2012
3
Salut, pour les amis de windows ... Bon ... il faut inclure windows.h puis winsock2.h ensuite, il faut linker avec ws2_32.lib ou .a puis dans le code initialiser ws2_32.dll par un appel de wsastartup() sans oublier d'appeler wsacleanup() lorsque l'appli se ferme et ceci autant de fois que wsastartup() a été invoqué. Un joli bronx ce windows. D'ailleurs vista n'est pas encore adolescent qu'un autre -windows 7- va renflouer le tiroir-caisse ça me gonfle prodigieusement et j'ai bien fait de ne pas l'acheter ça date du jour où j'ai juré ne plus jamais donner un seul centime à microsoft. C'est pas une question d'argent, mais de principes. Bref Linux c'est la classe, surtout pour les développeurs c'est vraiment adapté; retour à nos moutons
Le mieux est de regarder ma source "speech POP3" car elle contient un exemple de sockets sous windoze. Après à vous d'employer au mieux les directives pré-processeur pour exécuter le code correspondant à la plateforme sur laquelle le code sera compilé:

#ifdef WIN32
...includes windose
#else
...includes UNIX
#endif

MODAFINE pour l'authentification SMTP il faut carrément jeter ce code et effectuer une réelle conversation entre machines : le client alterne tout simplement les send() et les recv() en prenant juste soin d'encoder en MD5 le mot de passe, ce n'est pas plus compliqué que ça mais il faut chercher. CPPfrance propose un bon code en C pour l'encodage MD5 ça marche au poil je confirme. Un coup d'oeil rapide à la RFC822 qui spécifie le protocole SMTP et c'est tout!

En espérant vous avoir répondu merci les amis, bonne programmation à vous.
Messages postés
643
Date d'inscription
lundi 10 septembre 2007
Statut
Membre
Dernière intervention
15 juillet 2013

Salut, serait-il possible d'avoir le source pour Windows XP svp?
Thx
Messages postés
5
Date d'inscription
samedi 15 novembre 2008
Statut
Membre
Dernière intervention
10 mars 2011

salut j'ai un petit problème : j'aimerais que dans le corp du message que j'envoie il y est une saisi que j'ai faite auparavant ( une chaine de caractère de type char) j'ai essayez de remplacer le "bijour" par un nom de variable ou encore mettre %s mais la j'avoue que étant débutant je sèche

Sinon très bon code pour comprendre le fonctionnement du protocole smtp ;)
Messages postés
8
Date d'inscription
mardi 26 juin 2007
Statut
Membre
Dernière intervention
17 décembre 2008

Bonjour katsankat,

j'ai tester encore une fois votre code mais il lui manque l'authentification pour accéder au serveur smtp.

Pouvez vous m'aider sur ce problème.

Merci. je suis en attente de votre aide.

modafine.
Afficher les 21 commentaires

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.