Click here to Skip to main content
15,868,016 members
Articles / Desktop Programming / MFC
Article

IP Announce by Email

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

Screen shots of using Announce By Email utility

Introduction

This tool is used to collect information from the system by executing a command and then sending the information out to a specific destination through a network (via email through SMTP in this version. For information regarding SMTP, please ref. to: RFC821) even through Internet. 

Background

Have you ever called your friend to help you comfort your PC but gave up from his willingness to teach you what an IP address is whilst he was trying to connect to your computer from his office? Did your ever call your IT support engineer to resolve a simple problem but he wants to fill your mind with useless information?

Have you ever been called to support your friends, parents, customers or boss who has very poor knowledge of computers? Maybe their only experience is in reading and composing email with their computer. Does this often happen when you are far from them and they will tell you that you are the only one they trust? Therefore you might like to resolve the problem by connecting to their computer. When you try to do this, did it often frustrate you to explain what an IP address is?

Did you ever want to monitor the time when a computer booted up? Maybe you also wanted it to send you an announcement, after a user logs in, through a network (such as via email) rather than check the boring event log. Did you want the announcement to contain more useful information, such as what the IP address it is getting from DHCP? Did you ever want to know who logs into the computer?

This tool is just for you :)

Did you want to get a simple example of how to execute a command, send data via network and use SMTP, query registry for information, ­etc., for your program? 

The source code of this tool will provide you with a simple view of how to combine those technologies to complete a task. This is not the best, but I am giving a good try :)

How to Use

This tool will work as following process:

  1. Create a new process to run a console-based command provided by the system (such as ipconfig.exe).
  2. Redirect the standard output of the command execution and generate a message from this output information.
  3. Send the message to a specified destination.

To use this utility, simply run the executable program or run the program with some arguments (all arguments are optional).

usage: IPAnnounceByEmail [-p:X] [-s:IP] [-c:S] [-t:S] [-f:S] [-?]

       -p:X      Remote port to send to
       -s:IP     Server's IP address or host name
       -c:S      Command to execute
       -t:S      Target email address for the message to be send to
       -f:S      Source email address that the message is send from
       -?        Get this usage information

If the argument not be specified, the tool will execute the default command: "ipconfig /all". If the tool cannot find any default email account information from profile of current logon user also, the output will be send to default address: wesley_yang@sohu.com. These information can be changed in the source code:

#define COMMAND_TO_EXEC "ipconfig /all" // Change<BR>#define TARGET_ADDRESS "wesley_yang@sohu.com" // Change<BR>#define SOURCE_ADDRESS "wesley_yang@sohu.com"<BR>#define DEFAULT_SUBJECT "<IP announcement> "<BR>#define DEFAULT_SERVER_ADD "smtp.sohu.com"

After you change these definitions, you can then rebuild an EXE file and send it to your friend, or your customer.

This tool does not request an email client application. It sends email messages by an embedded method. For the current version of this tool that only support message announce via SMTP email, an SMTP server is required on the environment of the executing side.

Points of Interest

1. Synchronization of process:

In the very first version of this utility, I create new process to execute the command "ipconfig.exe". This utility runs properly, that means the output pipe can get correct and complete output from this command.

After I completed the testing of other function, I tried to execute a new command as "ping www.microsoft.com", the utility will not completely send the output from this execution this time. I found out that the output pipe actuarially hadn't got the whole output as we could see in console. This is caused by the synchronization problem that the main process does not wait for the child process to be completed. Therefore, I made some enhancement.

At first, return a handle of the child process:

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

Then, while create child process to execute the command, added a single to wait for the complication of command execution:

//Execute the command and get handle of the child process for<BR>    //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 ..." or<BR>    //"tracert ..." etc.
    if (WaitForSingleObject(hChildProcess, TIME_OUT_SETTING) ==<BR>        WAIT_TIMEOUT)
{
    printf ("The command execution time out!\n");
    TerminateProcess(hChildProcess, 0);
    printf ("The command is terminated!\n");

    writeLog(logFile, "Command execution time out!");
}

2. Transforming data through network:

In this utility, data transformation is very important. I'm using the socket2 API to send and receive data. Since the network communication capability is inside of the Windows system, the program can execute without other dependencies.

There will be 3 steps to send data through network:

  1. The very first step is to prepare the data to be send.
  2. After the data structure is filled and ready to be send, initialize the socket connection to the SMTP server will be the next.
  3. Then, send data to the server.
//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();

The basic networking function is in the header file: baseheader.h therefore the winsock2.h is needed to be included in the file.

3. Sending email message:

The email message is send based on SMTP protocol. This protocol is defined in the RFC821 (refer to: ftp://ftp.rfc-editor.org/in-notes/rfc821.txt).

After the TCP/IP connection to the SMTP server (default port is 25) be established, the data can be send to the server with format defined by SMTP protocol.

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<BR>    //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<BR>    //mail. If the SMTP-receiver can accept mail it responds with an<BR>    //OK reply.
    strcpy (Data2Srv, "MAIL FROM <");
    strcat (Data2Srv, msg.FromAdd);
    ...
    sendData (Data2Srv, ssmtp, FeedBack);
    writeLog(logFile, FeedBack);

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

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

    strcpy (Data2Srv, "SUBJECT: ");
    ...
    sendData (Data2Srv, ssmtp, FeedBack);
    writeLog(logFile, FeedBack);

    //End of SMTP message sending
    return true;
}

4. Retrieval default email account information:

At the very first version of this tool, the email account is defined in the source code. Although this will provide a channel for user that does not have SMTP email sending account, it will cause some inconvenience.

Therefore in this version, get email sending information from user profile be added in to code. The user profile that provide information of email account is stored in the registry key here:
HKEY_CURRENT_USER\Software\Microsoft\Internet Account Manager

To get those information, use these codes:

//Here query the registry to check if the default email <BR>//account setting is available or not.
//If yes, use those value to set the global various.    
//If no, use the default value defined in these codes.    
if (getRegInfo(STR_VALUE, "Software\\Microsoft\\Internet Account Manager",<BR>    "Default Mail Account", defMailAccount, NULL))
{
    defSmtpInfo = true;        
    strcpy (KEY,<BR>        "Software\\Microsoft\\Internet Account Manager\\Accounts\\");
    strcat (KEY, defMailAccount);    
}    
if (defSmtpInfo && getRegInfo(STR_VALUE, KEY,<BR>    "SMTP Email Address", msg.FromAdd = new char [REG_BUFF], NULL));
else msg.FromAdd = SOURCE_ADDRESS;

The function getRegInfo is defined in the baseheader.h header file.

The predefined email information still exists; meanwhile the tool can also get information for email sending in this order:

  1. Arguments. Using the information specified by the command argument.
  2. User profile. If required information for email sending is not in the argument, the tool will use the email account information that get from registry setting or so called user profile. The default account will be used.
  3. Defaults in code. If the execution information that this tool required neither in specified by argument nor possible to be get from user profile (such as default account does not exists in the registry), the default predefined information will be used.

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

 
GeneralPlease help me Pin
xulescuasu21-Feb-12 8:38
xulescuasu21-Feb-12 8:38 
GeneralThanks ^^ Pin
hhj113017-Dec-08 19:51
hhj113017-Dec-08 19:51 
QuestionLinker-Error in VS.Net 2003 Pin
Karlheinz24-Jul-07 10:17
Karlheinz24-Jul-07 10:17 
AnswerRe: Linker-Error in VS.Net 2003 Pin
hhj113017-Dec-08 19:57
hhj113017-Dec-08 19:57 
GeneralRe: Linker-Error in VS.Net 2003 Pin
Alan MacAree2-Dec-09 21:02
Alan MacAree2-Dec-09 21:02 
General530 authentication required Pin
rpuskarz14-Apr-04 13:41
rpuskarz14-Apr-04 13:41 
GeneralThanks! Pin
Matrix (R)Evolution27-Jun-03 23:02
Matrix (R)Evolution27-Jun-03 23:02 
GeneralNew development Pin
Matrix (R)Evolution24-Jun-03 23:58
Matrix (R)Evolution24-Jun-03 23:58 
GeneralRe: New development Pin
Puffel26-Jun-03 22:09
Puffel26-Jun-03 22:09 
GeneralHElp Pin
Matrix (R)Evolution22-Jun-03 23:36
Matrix (R)Evolution22-Jun-03 23:36 
GeneralRe: HElp Pin
Puffel23-Jun-03 16:34
Puffel23-Jun-03 16:34 
Generalplease remove it Pin
Andreas Saurwein28-Apr-03 0:30
Andreas Saurwein28-Apr-03 0:30 
GeneralRe: please remove it Pin
Tim Stubbs28-Apr-03 1:16
Tim Stubbs28-Apr-03 1:16 
GeneralRe: please remove it Pin
Andreas Saurwein28-Apr-03 1:44
Andreas Saurwein28-Apr-03 1:44 
GeneralRe: please remove it Pin
Tim Stubbs28-Apr-03 2:09
Tim Stubbs28-Apr-03 2:09 
GeneralRe: please remove it Pin
Andreas Saurwein28-Apr-03 2:35
Andreas Saurwein28-Apr-03 2:35 
GeneralRe: please remove it Pin
Simon.W28-Apr-03 2:03
Simon.W28-Apr-03 2:03 
GeneralRe: please remove it Pin
niknapalm28-Apr-03 7:08
niknapalm28-Apr-03 7:08 
GeneralRe: please remove it Pin
Puffel28-Apr-03 16:01
Puffel28-Apr-03 16:01 
GeneralRe: please remove it Pin
SexyLilDarkPaw28-May-06 5:15
SexyLilDarkPaw28-May-06 5:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.