Click here to Skip to main content
15,895,709 members
Articles / Desktop Programming / MFC

IP Announce by Email

Rate me:
Please Sign up or sign in to vote.
4.94/5 (18 votes)
26 Apr 2003CPOL5 min read 110.2K   3.8K   47  
Sends local computer's network information to a remote computer via email.
/* 

IP announcement by email
Version 1.0.01

By Wesley Yang.
2003 Feb. 28th

*/

// IPAnnounceByEmailCPP.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include "baseheader.h"

#define BUFFER_DEFAULT_SIZE 4096
#define CMD_BUFF 256
#define SMTP_DEFAULT_PORT 25
#define TIME_OUT_SETTING 20000

#define LOG_FILE_FULL_NAME "logIPA.log"
#define COMMAND_TO_EXEC "ipconfig /all"
#define TARGET_ADDRESS "wesley_yang@sohu.com"
#define SOURCE_ADDRESS "yangs@lzu.edu.cn"
#define DEFAULT_SUBJECT "<IP announcement> "
#define DEFAULT_SERVER_ADD "smtp.lzu.edu.cn"

SmtpMsg msg;
TCPServer srv;
SOCKET ssmtp;
char* commandToExec;
char szBuffer[BUFFER_DEFAULT_SIZE]; //Buffer to get response from server

HANDLE createChildProcess(char*);
bool getCmdResult(char*, LPTSTR);
bool setSmtpMessage(char*);
int connectToSmtpSrv(void);
bool sendSmtpAnnounce(void);
void validateArgs(int, char**);
bool init(int, char**);
bool quit(void);
bool getRegInfo (int, char*, char*, char*, int*);

int _tmain(int argc, _TCHAR* argv[])
{
	//Initialize the program at first
	init(argc, argv);
	
	//Here run the command to get the information of system (or some other).
	char cmdResult[BUFFER_DEFAULT_SIZE];
	ZeroMemory(&cmdResult, BUFFER_DEFAULT_SIZE);

	printf("Now running the command. Please wait...\n");
	getCmdResult(commandToExec, cmdResult);

	//Here save the log information.
	writeLog(logFile,cmdResult, TIME_STAMP_NO);

	//Here send the announcement.
	//Steps of sending announcement:
	// 1. Fill the structure of SmtpMsg
	// 2. Initialize the network connection
	// 3. Send announcement
	setSmtpMessage (cmdResult);
	initConn (srv.address, srv.port, &ssmtp);

	printf("Now sending the message. Please wait...\n");
	sendSmtpAnnounce();
	
	//Here quit the program
	quit();
	return 0;
}

bool init(int argc, char **argv)
{

/*The init() initialize the start environment. 
  The action of the init() will be:
    1. Initialize some global various' default value 
    2. Check the command line arguments
    3. Open the log file
*/	
	bool defSmtpInfo = false;
	char defMailAccount[REG_BUFF];
	char KEY[REG_BUFF];

	//Here query the registry to check if the default email account setting is available or not.
	//If yes, use those value to set the global various.
	//If no, use the default value defined in this codes.
	if (getRegInfo(STR_VALUE, "Software\\Microsoft\\Internet Account Manager", "Default Mail Account", defMailAccount, NULL))
	{
		defSmtpInfo = true;
		strcpy (KEY, "Software\\Microsoft\\Internet Account Manager\\Accounts\\");
		strcat (KEY, defMailAccount);
	}

    if (defSmtpInfo && getRegInfo(STR_VALUE, KEY, "SMTP Email Address", msg.FromAdd = new char [REG_BUFF], NULL));
	else msg.FromAdd = SOURCE_ADDRESS;
	msg.ToAdd = TARGET_ADDRESS;

	//Here define the subject of the announcement
	msg.Subject = new char[CMD_BUFF];
	strcpy(msg.Subject, DEFAULT_SUBJECT);
	strcat(msg.Subject, getNowTime());

	if (defSmtpInfo && getRegInfo(STR_VALUE, KEY, "SMTP Server", srv.address = new char [REG_BUFF], NULL));
	else srv.address = DEFAULT_SERVER_ADD;
	if (defSmtpInfo && getRegInfo(DW_VALUE, KEY, "SMTP Port", NULL, &srv.port));
	else srv.port = SMTP_DEFAULT_PORT;

	commandToExec = COMMAND_TO_EXEC;

	//Here validate the arguments
	validateArgs (argc, argv);

	//Open the log file
	logFile = openLog(LOG_FILE_FULL_NAME);

	return true;
}

bool quit(void)
{
/*The quit() clean the environment and prepare to exit.
  The action of the quit() will be:
    1. Close the log file
    2. Close the connection to SMTP server
    3. 
*/
	closeConn(ssmtp);
	closeLog(logFile);

	return true;
}

void printUsage(void)
{
	printf ("IP announcement by email version 0.1\n");
	printf ("By Wesley Y., 2003.Feb.20\n\n");
	printf ("usage: IpAnnounceByEmail [-p:X] [-s:IP] [-c:S] [-t:S] [-f:S] [-?]\n\n");
	printf ("       -p:X      Remote port to send to\n");
	printf ("       -s:IP     Server's IP address or host name\n");
	printf ("       -c:S      Command to execute\n");
	printf ("       -t:S      Target email address for the message to be send to\n");
	printf ("       -f:S      Source email address that the message is send from\n");
	printf ("       -?        Get this usage information\n");
	ExitProcess(0);
}

void validateArgs (int argc, char** argv)
{
/*This function check the arguments

*/
	int i;

	for (i=1; i<argc; i++)
	{
		if ((argv[i][0] == '-') || (argv[i][0] == '/'))
		{
            switch (tolower(argv[i][1])) //Convert argument information to lowercase
			{
			case 'p': 
				if (strlen(argv[i]) > 3)
					srv.port = atoi(&argv[i][3]);
				break;
			case 's': 
				if (strlen(argv[i]) > 3)
				{
                    srv.address = new char[CMD_BUFF];
					strcpy (srv.address, &argv[i][3]);
				}
				break;
			case 'c': 
				if (strlen(argv[i]) > 3)
				{
                    commandToExec = new char[CMD_BUFF];
					strcpy (commandToExec, &argv[i][3]);
				}
				break;	
			case 't': 
				if (strlen(argv[i]) > 3)
				{
					msg.ToAdd = new char[CMD_BUFF];
					strcpy (msg.ToAdd, &argv[i][3]);
				}
				break;
			case 'f': 
				if (strlen(argv[i]) > 3)
				{
					msg.FromAdd = new char[CMD_BUFF];
					strcpy (msg.FromAdd, &argv[i][3]);
				}
				break;
			case '?': 
				printUsage();
				break;
			default:
				break;
			}
		}
	}
}

HANDLE createChildProcess(char* cmdName)
{
	PROCESS_INFORMATION piProcInfo;
	STARTUPINFO siStartInfo;

	ZeroMemory(&piProcInfo,sizeof(PROCESS_INFORMATION));
	ZeroMemory(&siStartInfo,sizeof(STARTUPINFO));

	siStartInfo.cb = sizeof(STARTUPINFO);

	CreateProcess(NULL,
		cmdName,
		NULL,
		NULL,
		true,
		0,
		NULL,
		NULL,
		&siStartInfo,
		&piProcInfo);

	return piProcInfo.hProcess;
}

bool getCmdResult (char* cmdName, LPTSTR result)
{
/*This function creates a new process to execute the command and fill the result
  The steps of execute a command:
  1. Create a pipe to get the standard output from the process
  2. Execute the command as a child process and return the handle of this process
  3. Wait for the single of end of the child process until timeout
  4. Fill the result with the output of the child process

*/
	HANDLE hSaveStdOut, hChildStdOutWr, hChildStdOutRd, hChildStdOutRdDup, hChildProcess;
	
	SECURITY_ATTRIBUTES saAttr;
	bool fSuccess;
	DWORD dwRead;

	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
	saAttr.bInheritHandle = true;
	saAttr.lpSecurityDescriptor = NULL;

	hSaveStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

	if (!CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &saAttr, 0))
		ErrorExit ("Stdout pipe creation error!", logFile);

	if (!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdOutWr))
		ErrorExit ("Redirecting Stdout error!", logFile);

	fSuccess = DuplicateHandle (GetCurrentProcess(), 
		hChildStdOutRd, 
		GetCurrentProcess(), 
		&hChildStdOutRdDup, 
		0, 
		false, 
		DUPLICATE_SAME_ACCESS);
	if (!fSuccess) ErrorExit ("Duplicate handle error!", logFile);
	CloseHandle(hChildStdOutRd);
    
	//Execute the command and get handle of the child process for later use.
	hChildProcess=createChildProcess(cmdName);

	if (hChildProcess == NULL)
		ErrorExit ("Command execution error", logFile);

	if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdOut))
		ErrorExit ("Restor Stdout handle error!", logFile);

    //Here waiting for the command to be completed successfully. 
	//It is useful if command is time correlative such as "ping ..." etc.
    if (WaitForSingleObject(hChildProcess, TIME_OUT_SETTING) == WAIT_TIMEOUT)
	{
		printf ("The command execution time out!\n");
		TerminateProcess(hChildProcess, 0);
		printf ("The command is terminated!\n");
		
		writeLog(logFile, "Command execution time out!");
	}

	for (;;)
	{
		if (ReadFile(hChildStdOutRdDup, result, BUFFER_DEFAULT_SIZE, &dwRead, NULL) || dwRead==0) break;
	}

	return true;
}

bool setSmtpMessage (char* body)
{
	msg.MsgBody = body;
	return true;
}

bool sendSmtpAnnounce (void)
{
	char Data2Srv[BUFFER_DEFAULT_SIZE];
	char FeedBack[BUFFER_DEFAULT_SIZE];
	char* CRLF = "\r\n";

	
	ZeroMemory(Data2Srv, BUFFER_DEFAULT_SIZE);

	//HELO command session
	//Used to identify the sender-SMTP to the receiver-SMTP
	//The sender-SMTP establishes a two-way transmission channel to a receiver-SMTP
	strcpy (Data2Srv, "HELO ");
	strcat (Data2Srv, srv.address);
	strcat (Data2Srv, CRLF);
	sendData (Data2Srv, ssmtp, FeedBack);
	writeLog(logFile, FeedBack);

	//MAIL command session
	//SMTP-sender sends a MAIL command indicating the sender of the mail.  
	//If the SMTP-receiver can accept mail it responds with an OK reply.
	strcpy (Data2Srv, "MAIL FROM <");
	strcat (Data2Srv, msg.FromAdd);
	strcat (Data2Srv, ">");
	strcat (Data2Srv, CRLF);
	sendData (Data2Srv, ssmtp, FeedBack);
	writeLog(logFile, FeedBack);

	//RCPT command session
	//The SMTP-sender sends a RCPT command identifying a recipient of the mail.  
	//If the SMTP-receiver can accept mail for that recipient it responds with an OK reply
	strcpy (Data2Srv, "RCPT TO <");
	strcat (Data2Srv, msg.ToAdd);
	strcat (Data2Srv, ">");
	strcat (Data2Srv, CRLF);
	sendData (Data2Srv, ssmtp, FeedBack);
	writeLog(logFile, FeedBack);

	//DATA command session
	//The SMTP-sender sends the mail data, terminating with a special sequence.  
	//If the SMTP-receiver successfully processes the mail data it responds with an OK reply.
	strcpy (Data2Srv, "DATA ");
	strcat (Data2Srv, CRLF);
	sendData (Data2Srv, ssmtp, FeedBack);
	writeLog(logFile, FeedBack);

	strcpy (Data2Srv, "SUBJECT: ");
	strcat (Data2Srv, msg.Subject);
	strcat (Data2Srv, CRLF);
	strcat (Data2Srv, msg.MsgBody);
	strcat (Data2Srv, CRLF);
	strcat (Data2Srv, ".");
	strcat (Data2Srv, CRLF);
	sendData (Data2Srv, ssmtp, FeedBack);
	writeLog(logFile, FeedBack);

	//End of SMTP message sending
    return true;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader
China China
When I was 8, I touched a computer (SHARP PC1500, as I remembered^_^) firstly. Till 10, I could only changed rule of scroll counting in a game written in BASIC...

In the year 2001, I finally graduated from CS department of Lanzhou University.

What's to say, start work then Smile | :)

I like computer; like the way it give me that allow me to design what I want; like to make idea into reality on it…

Comments and Discussions