Hi Friends, today We need to send a simple alert mail from our application and I have wanted to send this email from C using sockets.
It isn't difficult, you need to open a socket connection to the server using the port of email service and exchange some messages to send the alert message.
All messages you have to send, should be terminated by "\r\n" and after each message you have to call to recv function to get the response from the server.
The first message to send to the Server is the HELO %s\r\n message, replacing %s with the server ip address.
After this message you have to send the EHLO\r\n message, this message will be responsed by the Server with all operations permited by the server.
If you need to send some login information to your email server, you'll need to send the auth\r\n message and after this, you'll have to send the user uid\r\n and pwd\r\n in base64 format.
To do this, I've used Openssl again.
At this point you have to send the information about the from address, to address, subject and body.
For ending the comunication with the server you need to send a blank line and after this blank line send a quit\r\n message.
Bellow I paste the code I've used to do this, I hope it'll be useful for you
// Mail.c : email function example
//
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#includee <sys/types.h>
#ifdef WIN32
#include <winsock.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <openssl/bio.h>
#include <openssl/evp.h>
#include "applink.c"
BIO_METHOD * BIO_f_base64(void);
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
char *base64(const unsigned char *input, int length);
int main (int argc, char* argv[])
{
char ret[2500]="";
// Init OpenSSL
_fmode=_O_BINARY;
CRYPTO_malloc_init();
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
ENGINE_load_builtin_engines();
ERR_load_crypto_strings();
return SendMail("uid@server.es","uidTo@server.es", "MailServerIp", "Subject", "UID","PWD", "Message");
}
/*
*
* Send Text Mail from user requested to the target user, using the server and the specified credentials.
*
*/
BOOL SendMail(const char* _From, const char* _To, const char* host,
const char* _Subject, const char* uid, const char* pwd, const char* _MessageFormat, ...)
{
int iProtocolPort = 0;
char szBuffer[4096] = "";
SOCKET sd;
struct sockaddr_in sa;
LPSERVENT lpServEntry;
va_list message_parts;
char message[65536];
int err=0;
char _SMTP[16]="";
#ifdef WIN32
WORD wVersionRequested;
WSADATA wsaData;
#endif
#ifdef WIN32
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData );
if ( err != 0 )
{
exit(1);
}
#endif
// traslating namehost to ip address
strcpy(_SMTP, GetIpAddress((char*)host));
// creating the Socket
sd = socket(PF_INET, SOCK_STREAM, 0);
if (sd == INVALID_SOCKET)
{
// Cannot open mail server socket!
return FALSE;
}
// Getting the mail port
lpServEntry = getservbyname("mail", 0);
// if we havent't a port, we use the default port to SMTP
if (!lpServEntry)
iProtocolPort = htons(IPPORT_SMTP);
else
iProtocolPort = lpServEntry->s_port;
memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr (_SMTP); /* Server IP*/
sa.sin_port = (iProtocolPort); /* Server Port*/
// Connecting to the Server
if(connect(sd, (struct sockaddr*) &sa, sizeof(sa)))
{
// Error connecting to the Server!
return FALSE;
}
// Initial response from the Server
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Init dialog
sprintf(szBuffer, "HELO %s\r\n", _SMTP);
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
sprintf(szBuffer,"ehlo\r\n");
send(sd,szBuffer,strlen(szBuffer),0);
recv(sd,szBuffer,sizeof(szBuffer),0);
// Sending login
strcpy(szBuffer, "auth login\r\n");
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send userid
sprintf(szBuffer,"%s\r\n", base64(uid, strlen(uid)));
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send Pwd
sprintf(szBuffer,"%s\r\n", base64(pwd, strlen(pwd)));
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// send From
sprintf(szBuffer, "MAIL FROM:<%s>\r\n", _From);
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send To
// repeat for each target address
sprintf(szBuffer, "RCPT TO:<%s>\r\n", _To);
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send Data
sprintf(szBuffer, "DATA\r\n");
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Preparing the string to send
va_start(message_parts, _MessageFormat);
vsprintf(message, _MessageFormat, message_parts);
va_end(message_parts);
// Setting Subject and Body
sprintf(szBuffer,"Subject: %s\r\n\r\n%s\r\n.\r\n",_Subject, message);
// Send a blank line to end the transmision
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Sending end command
sprintf(szBuffer, "quit\r\n");
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// closing the connection
#ifdef WIN32
closesocket (sd);
#else
close(sd);
#endif
return TRUE;
}
char *base64(const unsigned char *input, int length)
{
BIO *bmem, *b64;
BUF_MEM *bptr;
char *buff="";
b64 = BIO_new(BIO_f_base64());
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
buff = (char *)malloc(bptr->length);
memcpy(buff, bptr->data, bptr->length-1);
buff[bptr->length-1] = 0;
BIO_free_all(b64);
return buff;
}
/*
*
* Return Ip from hostname
*
*/
char* GetIpAddress(char *hostname)
{
struct sockaddr_in SocketAddress;
struct hostent *pHost = 0;
char aszIPAddresses[16];
int iCnt=0;
pHost = gethostbyname(hostname);
if(!pHost)
return "";
// get first server ip
memcpy(&SocketAddress.sin_addr, pHost->h_addr_list[0], pHost->h_length);
strcpy(aszIPAddresses, inet_ntoa(SocketAddress.sin_addr));
// returning ip
return aszIPAddresses;
}
Monday, March 31, 2008
Wednesday, March 5, 2008
SSL HTTP POST
Hi, friends
I'm developing a module to connect C programs with WebServices and newly I've used OpenSSL. Actually it hasn't very difficult, although I had some problem. It's very important to set properly the method to use. I'm connecting with a JBoss HTTPs WebService and I had to set this one:
meth = TLSv1_client_method();
ctx = SSL_CTX_new (meth);
I copy bellow the main function I had used, to send the HTTP POST message, I hope it'll be usefull for you:
int sendPOST(void* sd, SSL* ssl, ;char* server, char* port, char* post, char* action, char* csoap, char *response){
int ret=0;
char msg[5000]="";
char buff[5000]="";
int err=0;
int len=0;
char header[200]="";
// Setting HTTP Headers
sprintf(msg,"POST %s HTTP/1.1\r\n", post);
sprintf(header,"Host: %s:%s\r\n", server, port);
len=strlen(msg) ;
memcpy(msg + len , header, strlen(header));
len+=strlen(header);
strcpy(header,"Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n");
memcpy(msg + len, header, strlen(header));
len+=strlen(header);
sprintf(header,"Content-Length: %d\r\n", strlen(datos));
memcpy(msg + len, header, strlen(header));
len+=strlen(header);
sprintf(header,"SOAPAction: %s\r\n\r\n",action);
memcpy(msg + len, header, strlen(header));
len+=strlen(header);
// Adding csoap
memcpy(msg + len, datos, strlen(datos));
if(sd!=NULL){
// No SSL Connections
err=send((int)sd, msg, len + strlen(datos),0);
if (err == SOCKET_ERROR) {
printf("send() failed with error: %d\n", WSAGetLastError());
closesocket((int)sd);
WSACleanup();
exit(1);
}
do {
err = recv((int)sd, buff, sizeof(buff) - 1, 0);
if ( err > 0 )
printf("Bytes received: %d\n", err);
else if ( err == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( err > 0 );
}else{
// SSL Connections
err = SSL_write (ssl, msg, len + strlen(datos)); CHK_SSL(err);
err = SSL_read (ssl, buff, sizeof(buff) - 1);
CHK_SSL(err);
buff[err] = '\0';
SSL_shutdown (ssl);
}
strcpy(respuesta, buff);
return ret;
}
I'm developing a module to connect C programs with WebServices and newly I've used OpenSSL. Actually it hasn't very difficult, although I had some problem. It's very important to set properly the method to use. I'm connecting with a JBoss HTTPs WebService and I had to set this one:
meth = TLSv1_client_method();
ctx = SSL_CTX_new (meth);
I copy bellow the main function I had used, to send the HTTP POST message, I hope it'll be usefull for you:
int sendPOST(void* sd, SSL* ssl, ;char* server, char* port, char* post, char* action, char* csoap, char *response){
int ret=0;
char msg[5000]="";
char buff[5000]="";
int err=0;
int len=0;
char header[200]="";
// Setting HTTP Headers
sprintf(msg,"POST %s HTTP/1.1\r\n", post);
sprintf(header,"Host: %s:%s\r\n", server, port);
len=strlen(msg) ;
memcpy(msg + len , header, strlen(header));
len+=strlen(header);
strcpy(header,"Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n");
memcpy(msg + len, header, strlen(header));
len+=strlen(header);
sprintf(header,"Content-Length: %d\r\n", strlen(datos));
memcpy(msg + len, header, strlen(header));
len+=strlen(header);
sprintf(header,"SOAPAction: %s\r\n\r\n",action);
memcpy(msg + len, header, strlen(header));
len+=strlen(header);
// Adding csoap
memcpy(msg + len, datos, strlen(datos));
if(sd!=NULL){
// No SSL Connections
err=send((int)sd, msg, len + strlen(datos),0);
if (err == SOCKET_ERROR) {
printf("send() failed with error: %d\n", WSAGetLastError());
closesocket((int)sd);
WSACleanup();
exit(1);
}
do {
err = recv((int)sd, buff, sizeof(buff) - 1, 0);
if ( err > 0 )
printf("Bytes received: %d\n", err);
else if ( err == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( err > 0 );
}else{
// SSL Connections
err = SSL_write (ssl, msg, len + strlen(datos)); CHK_SSL(err);
err = SSL_read (ssl, buff, sizeof(buff) - 1);
CHK_SSL(err);
buff[err] = '\0';
SSL_shutdown (ssl);
}
strcpy(respuesta, buff);
return ret;
}
Subscribe to:
Posts (Atom)