/*
    XDemo64: SMTP demo

    Compiler: BC++ 3.1
    Compile mode: large
    Project: user.c
             v7000.c
             vModbus.c           [after vcom3002.lib]
             Vsocket.c
             ..\Lib\7186EL.Lib
             ..\Lib\tcp_dm32.lib
             ..\Lib\VcomNNNN.Lib, with NNNN being the lib file's version.

    The Simple Mail Transfer Protocol(SMTP) is used as the common mechanism for transporting 
    electronic mail among different hosts within the Department of Defense Internet protocol suite.
    A user's SMTP process opens a TCP connection to a server SMTP process on a remote host and send 
    mail across the connection. 
    The server SMTP listens for a TCP connection on a well-known port (25).
    [Model for SMTP Use]
                  +----------+                +----------+
                  |          |                |          |
                  |          |                |          |
    +------+      |  Sender  |Commands/Replies| Receiver |
    |Sender|      |   MTA    |<-------------->|    MTA   |      +------+
    |      |<---->|          | TCP connection |          |<---->| File |
    |System|      |          |                |          |      |System|
    +------+      +----------+                +----------+      +------+
   
    uPAC-7186EX    Sender-SMTP                Receiver-SMTP   User MailBox
    *MAT (message transfer agent)

    The SMTP provides mechanisms for the transmission of mail; directly
    from the sending user's host to the receiving user's host.
    If you need the detail in SMTP,please refer to RFC821

    Follow the executing steps below to send the e-mail without changing the source code.
    Step 1:
    19smtp 210.241.239.69 or 19SMTP 210.241.239.69 -->Change the SMTP server
    19from sean@icpdas.com or 19FROM test@test.com -->Change the MAIL FROM address
    19to sean@icpdas.com or 19TO test@test.com     -->Change the MAIL TO address
    19s 1                                          -->Build a socket to connect to the SMTP server
    Step 2:
    Load a file to the uPAC-7186EX, such as 'Mail.ini', but must follow the rules:
        1.Add the string 'Subject' in this file, because NO subject e-mail will reject by SMTP server
        2.Add the character '.' in end of file, because the DATA process will end by detecting this character.

    Subject:Test SMTP
        Hello!!
        This is a test Mail
        .

    The client functions consist of the ReceiveSocketBinaryCmd(),KillSockets(),BuildSockets()
    and SendSocketBinaryCmd() in "Vsocket.C".
    
    Hardware: uPAC-7186EX * 1
              uPAC-7186EX (IP:192.168.254.30)
    SMTP server:10.0.0.5 (ICPDAS SMTP server)

    Note: Run this demo, you can load one extra text file into uPAC-7186EX.
         (You can write the data in the Mail.ini you want to send for this demo).

    [Dec 18, 2008] by Liam 
*/

#include<string.h>
#include<stdio.h>
#include "..\lib\7186e.h"
#include "..\lib\tcpip32.h"
#include "..\lib\vxcomm.h"
#include "Vsocket.h"

int iSocketflag;
char InBuf[1023],OutBuf[1023]; //InBuf:the buffer of receing ,OutBuf:the buffer of sending
int iOutskt;                   //the socket number of connecting
unsigned int iPort;            //the SMTP server port number
unsigned char iIpStr[17];      //the SMTP server IP 
static FILE_DATA far *config;  
int SmtpMode;
int Recesucceed=0;
unsigned long stime;
char HELO[]="HELO ICPDAS_Sean\r\n"; 
char MAIL[]="<liam_lin@icpdas.com>";  //Change the mail address to your
char RCPT[]="<liam_lin@icpdas.com>";  //Change the mail address where you want to send

unsigned long FSeek(FILE_DATA far *file_pointer,char cMark,unsigned long lStart,int iTh,char *sstring);

void UserCount(void)
{
    /*
    User's timer trigger function.
    Please refer to XDemo04 for detail description.
    Please refer to XDemo09 for example code.
    */
}

void UserInit(void)
{
    /*
    Initialize user's program.
    Please refer to XDemo04 for detail description.
    Please refer to XDemo09 for example code.
    */  

    /*
    All of the program user.c needn't function Installcom().
    Becuase they have install When the Xserver initialize.
    If you want to change the baud rate.data format, 
    please using the function SetBaudrate().SetDataFormat().
    */
    
    InitLib();

    SetBaudrate1(115200L);
    iSocketflag=0;
    SmtpMode=0;
    
    sprintf(iIpStr, "10.0.0.5"); //SMTP server IP 
    iPort=25;   //SMTP server port 25
    printCom1("IpStr=%10s, iPort=%5d\n\r", iIpStr, iPort);
    config=GetFileInfoByName("Mail.ini");
}

void UserLoopFun(void)
{
    /*
    VxComm.exe will call this function every scan time
    Please refer to XDemo11 for Real-time I/O control
    */    

    int iRet, i;
    int icheck;

    extern int errno;
    
    if(iSocketflag>0)
    {
        iRet=ReceiveSocketBinaryCmd(iOutskt, InBuf, sizeof(InBuf), 700);
        if (iRet==-1)// read error
        {
            if(errno==ETIMEDOUT) //Detect whether the error of recv is caused by timeout.
            {
                if(GetTimeTicks()-stime<8000)   //8 sec
                {
                    Recesucceed=1;
                    printCom1("echo Receive timeout \r\n");
                }
                else
                {
                    printCom1("Receive timeout over 8 sec\r\n",iRet);
                    KillSocket(iOutskt);
                    Recesucceed=0;
                    iSocketflag=0;
                    SmtpMode=0;
                }
            }
            else
            {
                Recesucceed=0;
                printCom1("echo Receive error,code(%d)\r\n",iRet);
                KillSocket(iOutskt);
                iSocketflag=0;
                SmtpMode=0;
            }
        }
        else 
        {
            printCom1("%d, %s\r\n", SmtpMode+1, InBuf);
            sscanf(InBuf, "%d", &icheck);
            if(icheck!=221) //221 means the SMTP server return sending mail successfully and quit this connection
            {
                Recesucceed=0;
                if(Recesucceed==0)
                {
                    switch(SmtpMode)
                    {
                        case 0:
                            strcpy(OutBuf,HELO);
                            break;
                        case 1:
                            sprintf(OutBuf,"MAIL FROM:%s\r\n",MAIL);
                            break;
                        case 2:
                            sprintf(OutBuf,"RCPT TO:%s\r\n",RCPT);
                            break;
                        case 3:
                            strcpy(OutBuf,"DATA\r\n");
                            break;
                        case 4:
                            sprintf(OutBuf,"From:%s\r\nTo:%ls\r\n",MAIL,RCPT);
                            if(config!=NULL)
                                strcat(OutBuf,config->addr);
                            else
                                strcat(OutBuf,"Subject:Test Mail\r\nThis is a test mail\r\n.\r\n");
                            break;
                        case 5:
                            strcpy(OutBuf,"QUIT\r\n");
                            break;
                    }
                    
                    iRet=SendSocketBinaryCmd(iOutskt, OutBuf, strlen(OutBuf));
                    if (iRet==-1)// write error
                    {               
                        printCom1("echo Send error,code(%d)\r\n",iRet);
                        return;
                    }
                    else
                    {
                        stime=GetTimeTicks();
                        printCom1("Send the command(%s) from client\r\n",OutBuf);
                    }
                    SmtpMode++; 
                }
            }
            else
            {
                Recesucceed=0;
                printCom1("Send the mail successfully and close the connection!!\r\n");
                KillSocket(iOutskt);
                iSocketflag=0;
                SmtpMode=0;
            }
        }
    }
}

int UserCmd(unsigned char *Cmd,unsigned char *Response)
{
    /*  
    Xserver executes this function when received a package 
    form TCP port 10000 and the first two bytes are "19".
    
    Funtion of Xserver, Please refer to XDemo04 for detail description.
    */  

    int start;
    char sCommand[10], sParameter[50];
    
    strlwr(Cmd);
    sscanf(Cmd,"%s %s", &sCommand, &sParameter);
    printCom1("%s, %s\r\n", sCommand, sParameter);
    if(!strcmp(sCommand, "smtp"))
        strcpy(iIpStr, sParameter);
    if(!strcmp(sCommand, "from"))
        strcpy(MAIL, sParameter);
    if(!strcmp(sCommand, "to"))
        strcpy(RCPT, sParameter);    
                    
    if(Cmd[0]=='s')  //Build a socket to connect to the SMTP server
    {
        sscanf(Cmd+1,"%d", &start);
        if(start==1)
        {
            if(!iSocketflag)
            {
                iOutskt=BuildSocket(iIpStr, iPort, 2000);  //buildsockets
                printCom1("Socket number:%d!!\r\n", iOutskt);
                if (iOutskt==-1){
                    printCom1("connect error!!\r\n");
                    iSocketflag=0;
                }
                else{
                    iSocketflag=1;
                    start=0;
                }            
            }       
        }       
    }           
    
    return 1;   /* return error */
}

int VcomUserBinaryCmd(TCPREADDATA *p)
{
    /* 
    VXCOMM.EXE 2.6.12(04,Sep,2001) or later will support this function.

    Xserver executes this function when received a package 
    form TCP port 10000 and the first two bytes are "23".
    
    Please refer to XDemo04 for detail description.
    Please refer to XDemo23 for example code.
    */
    return 1;   /* any value will be accept */
}

int VcomCmdUser(TCPREADDATA *p)  
{ 
    /*
    VCOM3005 (Feb,22,2002) or later will call this function for PortUser.
    When packets received by TCP PORT PortUser(user defined) 
    of 7188E/8000E, Xserver will call this function.

    Please refer to XDemo04 for detail description.
    */
    VcomSendSocket(p->Socket, p->ReadUartChar, p->Length);
    return 1;   /* any value will be accept */  
}

void PortUserStart(int skt)
{
    /* 
    XS8_3200.Lib Version 3.2.00 (20,Apr,2004) 
    or later version supports this function.
    
    When a TCP/IP client connects to the 7188E/8000E via the user's 
    defined port(PortUser), the Xserver calls the function once.

    Please refer to XDemo04 for detail description.
    */
    
    skt=skt; //do nothing
}
  
void Port9999Start(int skt)
{
    /* 
    XS8_3200.Lib Version 3.2.00 (20,Apr,2004) 
    or later version supports this function.
    
    When a TCP/IP client connects to the 7188E/8000E TCP port 9999, 
    the Xserver calls the function once.
 
    Please refer to XDemo04 for detail description.
    */
    
    skt=skt; //do nothing
}
 
void Port502Start(int skt)
{
    /* 
    XS8_3200.Lib Version 3.2.00 (20,Apr,2004) 
    or later version supports this function.
    
    When a TCP/IP client connects to the 7188E/8000E TCP port 502, 
    the Xserver calls the function once.
    
    Please refer to XDemo04 for detail description.
    */
    
    skt=skt; //do nothing
}
