Thread: Sending a simple email in C++?

  1. #1
    Registered User
    Join Date
    Apr 2010
    Posts
    5

    Sending a simple email in C++?

    Hey,

    I'm writing a program for a highschool programming assignment, and I'd like one of the features of the program being able to send a simple email updating the user of the status of the program.

    How do you go about sending a simple email in C++?

    any help would be appriciated,

    thanks,

    Coukapecker

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    If you don't have to do this, don't. It is not simple.

    If you still want to, you need to explain yourself better: why would the program have to send the user an email? They are on the same computer.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by Coukapecker View Post
    Hey,

    I'm writing a program for a highschool programming assignment, and I'd like one of the features of the program being able to send a simple email updating the user of the status of the program.

    How do you go about sending a simple email in C++?

    any help would be appriciated,

    thanks,

    Coukapecker
    Basically, you'll need to open a network socket, and then send the email commands over it (just Google the email RFC for the specs). Alternately, there are probably some libraries out there that you can use, too.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Registered User
    Join Date
    Apr 2010
    Posts
    5
    If you don't have to do this, don't. It is not simple.

    If you still want to, you need to explain yourself better: why would the program have to send the user an email? They are on the same computer.
    I've already put it in my program layout that I would; so it looks bad if I dont actually manage to acomplish doing it ;\. Kinda dug myself a hole lol.

    I would like the program to send an email to my teachers email address, emailing text the program will generate. The program is a business simulation and compile text about a hypothetical business together, then send an email to her. It doesn't need attatchments, encryption, all it needs its to send a basic email including To, From, Subject, and Body parts of the email.

    EDIT: I found some code, but for some reason its not working for me, is it working for anyone else?

    All credit of the following code goes to Mayukh Bose:

    SMTPDemo.cpp:

    Code:
    #include <stdio.h>
    #include <windows.h>
    #ifdef WIN32
    extern "C" {
    int send_mail(const char *smtpserver, const char *from, const char *to, 
    				const char *subject, const char *replyto, const char *msg);
    }
    #else
    #include "smtpfuncs.h"
    #endif
    
    int main(int argc, char* argv[])
    {
    	if (send_mail("smtp.gmail.com", "[email protected]", "[email protected]",
    				"My Subject", 
    				"[email protected]", 
    				"Hello test test test.") != 0)
    		MessageBox(NULL, "Failed", "bonjour(s)", MB_OK);
    	else
    		MessageBox(NULL, "Succsess", "bonjour(s)", MB_OK);
    	return 0;
    }
    smtpfuncs.h :
    Code:
    #ifndef __SMTPFUNCS_H_2003_11_15__
    #define __SMTPFUNCS_H_2003_11_15__
    
    #ifdef WIN32
    #include <winsock2.h>
    #include <io.h>
    #else
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <unistd.h>
    
    #define INVALID_SOCKET	-1
    #define SOCKET_ERROR	-1
    #endif
    
    #ifndef FALSE
    #define FALSE	0
    #endif
    
    #ifndef TRUE
    #define TRUE	1
    #endif
    
    #ifndef	NULL
    #define	NULL	0
    #endif
    
    #ifndef ERROR
    #define ERROR	-1
    #endif
    
    /* Mail server status codes */
    #define	MAIL_WELCOME	220
    #define MAIL_OK			250
    #define MAIL_GO_AHEAD	354
    #define MAIL_GOODBYE	221
    
    /* Error codes returned by send_mail */
    #define E_NO_SOCKET_CONN	-1
    #define E_PROTOCOL_ERROR	-2
    
    int send_mail(const char *smtpserver, const char *from, const char *to, 
    				const char *subject, const char *replyto, const char *msg);
    int connect_to_server(const char *server);
    int send_command(int n_sock, const char *prefix, const char *cmd, 
    					const char *suffix, int ret_code);
    int send_mail_message(int n_sock, const char *from, const char *to, 
    						const char *subject, const char *replyto, const char *msg);
    
    
    #ifdef WIN32
    int startup_sockets_lib(void);
    int cleanup_sockets_lib(void);
    #define snprintf  _snprintf
    #endif
    
    #endif
    smtpfuncs.c:
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    #include "smtpfuncs.h"
    
    int send_mail(const char *smtpserver, const char *from, const char *to, 
    					const char *subject, const char *replyto, const char *msg)
    {
    	int n_socket;
    	int n_retval = 0;
    
    #ifdef WIN32
    	startup_sockets_lib();
    #endif
    
    	/* First connect the socket to the SMTP server */
    	if ((n_socket = connect_to_server(smtpserver)) == ERROR) 
    		n_retval = E_NO_SOCKET_CONN;
    
    	/* All connected. Now send the relevant commands to initiate a mail transfer */
    	if (n_retval == 0 && send_command(n_socket, "MAIL From:<", from, ">\r\n", MAIL_OK) == ERROR)
    		n_retval = E_PROTOCOL_ERROR;
    	if (n_retval == 0 && send_command(n_socket, "RCPT To:<", to, ">\r\n", MAIL_OK) == ERROR) 
    		n_retval = E_PROTOCOL_ERROR;
    
    	/* Now send the actual message */
    	if (n_retval == 0 && send_command(n_socket, "", "DATA", "\r\n", MAIL_GO_AHEAD) == ERROR) 
    		n_retval = E_PROTOCOL_ERROR;
    	if (n_retval == 0 && send_mail_message(n_socket, from, to, subject, replyto, msg) == ERROR) 
    		n_retval = E_PROTOCOL_ERROR;
    
    	/* Now tell the mail server that we're done */
    	if (n_retval == 0 && send_command(n_socket, "", "QUIT", "\r\n", MAIL_GOODBYE) == ERROR) 
    		n_retval = E_PROTOCOL_ERROR;
    
    	/* Now close up the socket and clean up */
    	if (close(n_socket) == ERROR) {
    		fprintf(stderr, "Could not close socket.\n");
    		n_retval = ERROR;
    	}
    
    #ifdef WIN32
    	cleanup_sockets_lib();
    #endif
    
    	return n_retval;
    }
    
    int connect_to_server(const char *server)
    {
    	struct hostent *host;
    	struct in_addr	inp;
    	struct protoent *proto;
    	struct sockaddr_in sa;
    	int n_sock;
    #define SMTP_PORT	   25
    #define BUFSIZE		4096
    	char s_buf[BUFSIZE] = "";
    	int n_ret;
    
    	/* First resolve the hostname */
    	host = gethostbyname(server);
    	if (host == NULL) {
    		fprintf(stderr, "Could not resolve hostname %s. Aborting...\n", server);
    		return ERROR;
    	}
    
    	memcpy(&inp, host->h_addr_list[0], host->h_length);
    
    	/* Next get the entry for TCP protocol */
    	if ((proto = getprotobyname("tcp")) == NULL) {
    		fprintf(stderr, "Could not get the protocol for TCP. Aborting...\n");
    		return ERROR;	
    	}
    
    	/* Now create the socket structure */
    	if ((n_sock = socket(PF_INET, SOCK_STREAM, proto->p_proto)) == INVALID_SOCKET) {
    		fprintf(stderr, "Could not create a TCP socket. Aborting...\n");
    		return ERROR;
    	}
    
    	/* Now connect the socket */
    	memset(&sa, 0, sizeof(sa));
    	sa.sin_addr = inp;
    	sa.sin_family = host->h_addrtype;
    	sa.sin_port = htons(SMTP_PORT);
    	if (connect(n_sock, (struct sockaddr *)&sa, sizeof(sa)) == SOCKET_ERROR) {
    		fprintf(stderr, "Connection refused by host %s.", server);
    		return ERROR;
    	}
    
    	/* Now read the welcome message */
    	n_ret = recv(n_sock, s_buf, BUFSIZE, 0);
    	
    	return n_sock;
    }
    
    int send_command(int n_sock, const char *prefix, const char *cmd, 
    						const char *suffix, int ret_code)
    {
    #define BUFSIZE		4096
    	char s_buf[BUFSIZE] = "";
    	char s_buf2[50];
    	
     	strncpy(s_buf, prefix, BUFSIZE);
    	strncat(s_buf, cmd, BUFSIZE);
    	strncat(s_buf, suffix, BUFSIZE);
    
    	if (send(n_sock, s_buf, strlen(s_buf), 0) == SOCKET_ERROR) {
    		fprintf(stderr, "Could not send command string %s to server.", s_buf);
    		return ERROR;
    	}
    
    	/* Now read the response. */
    	recv(n_sock, s_buf, BUFSIZE, 0);
    
    	/* Now check if the ret_code is in the buf */
    	sprintf(s_buf2, "%d", ret_code);
    
    	if (strstr(s_buf, s_buf2) != NULL)
    		return TRUE;
    	else
    		return ERROR;
    }
    
    int send_mail_message(int n_sock, const char *from, const char *to,
    							const char *subject, const char *replyto, const char *msg)
    {
    #define BUFSIZE		4096
    #define BUFSIZE2	100
    #define MSG_TERM	"\r\n.\r\n"
    #define MAIL_AGENT	"Mayukh's SMTP code (http://www.mayukhbose.com/freebies/c-code.php)"
    	char s_buf[BUFSIZE];
    	char s_buf2[BUFSIZE2];
    	time_t t_now = time(NULL);
    	int n_ret;
    
    	/* First prepare the envelope */
    	strftime(s_buf2, BUFSIZE2, "%a, %d %b %Y  %H:%M:%S +0000", gmtime(&t_now));
    
    	snprintf(s_buf, BUFSIZE, "Date: %s\r\nFrom: %s\r\nTo: %s\r\nSubject: %s\r\nX-Mailer: %s\r\nReply-To: %s\r\n\r\n",
    				s_buf2, from, to, subject, MAIL_AGENT, replyto); 
    
    	/* Send the envelope */
    	if (send(n_sock, s_buf, strlen(s_buf), 0) == SOCKET_ERROR) {
    		fprintf(stderr, "Could not send message header: %s", s_buf);
    		return ERROR;
    	}
    
    	/* Now send the message */
    	if (send(n_sock, msg, strlen(msg), 0) == SOCKET_ERROR) {
    		fprintf(stderr, "Could not send the message %s\n", msg);
    		return ERROR;
    	}
    
    	/* Now send the terminator*/
    	if (send(n_sock, MSG_TERM, strlen(MSG_TERM), 0) == SOCKET_ERROR) {
    		fprintf(stderr, "Could not send the message terminator.\n", msg);
    		return ERROR;
    	}
    
    	/* Read and discard the returned message ID */
    	n_ret = recv(n_sock, s_buf, BUFSIZE, 0);
    
    	return TRUE;
    }
    
    #ifdef WIN32
    /* 
     * Routines for  Windows Socket Library
     */
    int startup_sockets_lib(void)
    {
    	WORD wVersionRequested;
    	WSADATA wsaData;
    	int n_err;
     
    	wVersionRequested = MAKEWORD( 1, 1 );
     
    	n_err = WSAStartup( wVersionRequested, &wsaData );
    	if (n_err != 0) {
    		fprintf(stderr, "Could not find winsock.dll.Aborting...\n");
    		return FALSE;
    	}
      
    	if (LOBYTE( wsaData.wVersion ) != 1 ||
    			HIBYTE( wsaData.wVersion ) != 1) {
    		fprintf(stderr, "Could not find w1.1 version of winsock.dll.Aborting...\n");
    		WSACleanup();
    		return FALSE; 
    	}
     
    	return TRUE; 
    }
    
    int cleanup_sockets_lib(void)
    {
    	WSACleanup();
    	return TRUE;
    }
    
    #endif
    Its giving me the error message " Connection refused by host xxx. Could not close socket".

    I've tried multiple SMTP hosts now and all of them give the same error message, leading me to believe the code is wrong or my computer is messing it up ;\.

    Anyone familiar with smtp protocol able to see anything wrong with this? Outdated method maybe?
    Last edited by Coukapecker; 04-09-2010 at 12:06 PM.

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Not an SMTP expert, but isn't a login customary for SMTP?

  6. #6
    Registered User
    Join Date
    Apr 2010
    Posts
    5
    I always thought that too, the credentials to the network, but there are plenty of "email spoofers" out there that send emails posing at someone elses email, and they wouldn't be able to do that if all methods needed credentials... I assumed this was one of those methods?

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Coukapecker View Post
    I've tried multiple SMTP hosts now and all of them give the same error message, leading me to believe the code is wrong or my computer is messing it up ;\.
    I was excited when I saw that smtp.gmail.com bit there, because I thought, wow, I can start spoofing emails from home again As you may have deduced from your investigations, it is easy enough to set what ever From: address you want doing mail up manually this way.

    Once upon a time, you did not even need to use an external server. You can run a mailserver on your desktop, it is not that hard. This is still possible, but the problem is, ISPs "whitelist" who they will receive mail from. So if you send it directly from your machine, the mail will automatically be rejected by almost everyone.

    This is because of of the spam industry. So I suspect there is no way gmail will let you just use their smtp server in a way that is 100% compatible with anonymous spamming either -- that service would get swamped.

    However, you should be able to do this with your own smtp server, if you do a login negotiation as tabstop says, and you will have to use the correct From: address. That means the program will also have to include some configuration for the user to enter:

    1) their smtp server
    2) their username and password

    Quote Originally Posted by Coukapecker View Post
    I always thought that too, the credentials to the network, but there are plenty of "email spoofers" out there that send emails posing at someone elses email, and they wouldn't be able to do that if all methods needed credentials... I assumed this was one of those methods?
    They can do this because they have access to an accepted smtp server that will allow them to spoof the "From:", which is unusual, that's the whole point of the whitelisting, but I imagine if you are in the spam business and can dish out some cash, you may be able to find some money hungry ISPs around who aren't worried about getting taken off the list. Like I said, I don't think Joe Average can do this so easily now (maybe I'm wrong, I've never heard of public "email spoofers", that was something I learnt with perl).
    Last edited by MK27; 04-09-2010 at 12:40 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C code for Sending Email with attachment
    By Mr coder in forum C Programming
    Replies: 5
    Last Post: 03-06-2009, 08:15 AM
  2. Storing names and email address.
    By arya6000 in forum C Programming
    Replies: 15
    Last Post: 11-19-2008, 03:47 AM
  3. Sending Email via C
    By fguy817817 in forum Networking/Device Communication
    Replies: 1
    Last Post: 09-04-2008, 01:51 PM
  4. Simple sockets - sending error
    By More_Coffee in forum Networking/Device Communication
    Replies: 4
    Last Post: 04-15-2007, 04:41 AM
  5. a doubt about sending an array to a function
    By louis_mine in forum C Programming
    Replies: 13
    Last Post: 05-14-2005, 11:50 PM