";
const char 
      *userID="watashi";
const char *passwd="uso800";
const int 
      port=587;
      /* Import 
      Library: Link with ws2_32.lib */
#include <stdio.h>
#include 
      <string.h>
#include <winsock2.h>
      /*ソケットsに文字列データdataを送信する関数*/
void sendData(SOCKET s, char 
      *data)
{
    
      send(s,data,strlen(data),0);
}
      /*ソケットsからバッファサイズbuffsizeのデータバッファdatabuffに
データを受け取る関数 返す値は取得バイト数*/
int 
      receiveData(SOCKET s, char *databuff, int 
      buffsize)
{
    char 
      *p=databuff;
    int i;
    for 
      (i=0;i<buffsize;i++) *p++=0;
    return 
      recv(s,databuff,buffsize,0);
}
      /**************** for printing information  HEAD 
      ************************/
#ifdef REQUEST_INFO
void 
      printWinsockInfo(WSADATA *wsaData)
{
    union 
      {
        short int 
      s;
        unsigned char 
      c[2];
    } v,hv;
    if 
      (wsaData==NULL) return;
    
      v.s=wsaData->wVersion;
    
      hv.s=wsaData->wHighVersion;
    printf("== winsock 
      information ==\n");
    printf("winsock 
      version   = %d.%d\n",v.c[0],v.c[1]);
    
      printf("winsock HighVer   = 
      %d.%d\n",hv.c[0],hv.c[1]);
    
      printf("Description       = 
      %s\n",wsaData->szDescription);
    
      printf("SystemStatus      = %s\n" 
      ,wsaData->szSystemStatus);
    printf("Max 
      Sockets       = %d\n" 
      ,wsaData->iMaxSockets);
    printf("Max UDP byte size 
      = %d\n" ,wsaData->iMaxUdpDg);
    
      printf("\n");
}
void printServerInfo(LPHOSTENT 
      lpHost)
{
    int i;
    if 
      (lpHost==NULL) return;
    printf("== server information 
      ==\n");
    printf("host 
      name      = %s\n" , 
      lpHost->h_name);
    printf("address type   
      = %d\n" , lpHost->h_addrtype); /*AF_INETは2*/
    
      printf("address length = %d\n" , 
      lpHost->h_length);
    for(i = 0 ; 
      lpHost->h_aliases[i] ; i++) 
      {
        
      printf("aliases        = %s\n" , 
      lpHost->h_aliases[i]);
    }
          for(i = 0 ; lpHost->h_addr_list[i] ; 
      i++) {
        IN_ADDR 
      *ip;
        ip = (IN_ADDR 
      *)lpHost->h_addr_list[i];
        
      printf("IP address     = %s\n" , 
      inet_ntoa(*ip));
    }
    
      printf("\n");
}
void printServiceInfo(LPSERVENT 
      lpServ)
{
    int i;
    if 
      (lpServ==NULL) return;
    printf("== service 
      information ==\n");
    printf("service name = %s\n" , 
      lpServ->s_name);
    for(i = 0 ; 
      lpServ->s_aliases[i] ; i++) 
      {
        
      printf("aliases      = %s\n" , 
      lpServ->s_aliases[i]);
    }
    
      printf("port number  = %d\n" , 
      lpServ->s_port);
    
      printf("protocol     = %s\n" , 
      lpServ->s_proto);
    printf("\n");
}
void 
      printPortInfo(int port)
{
    printf("== port number 
      information ==\n");
    printf("port number = %d\n" , 
      ntohs((short)port));
    
      /*ntohsはホストバイトオーダーに戻す関数*/
    
      printf("\n");
}
#endif
/**************** for printing 
      information  TAIL ************************/
      /************************************************************
ソケットをオープンし,目的のサーバのポートに接続する
server:     
      サーバの名前(ドメイン名,ドメインを省略してはいけない)
            
      例えばaaaa.tokyo-ct.ac.jp
servicename:"smtp"とか"http"などのサービスの名前,
            
      次のところに名前の一覧がある
            
      Windowsシステムのsystem32\drivers\etc\services
service:    
      サービスのポート番号,smtpなら25,httpなら80など
            
      この情報は,servicenameが不明の場合に必要なだけで,
            
      通常は使われない
不成功ならINVALID_SOCKETを返す
*************************************************************/
SOCKET 
      connectSocket(const char *server, char *servicename, short int 
      service)
{
    WSADATA wsaData; 
      /*winsock*/
    LPHOSTENT lpHost;
    
      LPSERVENT lpServ;
    SOCKET sock;
    
      SOCKADDR_IN sockAddr;
    int port; 
      /*ポート番号*/
    int status;
          
      /*winsockをver1.1で初期化を要求*/
    
      status=WSAStartup(MAKEWORD(1, 1), &wsaData);
    if 
      (status != 0) {
        
      fprintf(stderr,"WSAStartup() 
      failed\n");
        return 
      INVALID_SOCKET;
    }
          
      /*サーバ名からホストの情報を得る*/
    lpHost = 
      gethostbyname(server);
    if(lpHost == NULL) 
      {
        fprintf(stderr,"server 
      name error\n");
        
      WSACleanup();
        return 
      INVALID_SOCKET;
    }
          
      /*サービス情報からポート番号取得*/
    lpServ = 
      getservbyname(servicename, NULL);
    if (lpServ == 
      NULL) {
        
      port=htons(service);
        
      /*ホストバイトオーダーからネットワークバイトオーダー(ビッグエンディアン)に変換*/
    } else 
      {
        
      port=lpServ->s_port;
    }
    
      #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printWinsockInfo(&wsaData); 
      /*Winsocの情報表示*/
        
      printServerInfo(lpHost);    
      /*サーバの情報表示*/
        
      printServiceInfo(lpServ);   
      /*サービスの情報表示*/
        
      printPortInfo(port);        
      /*ポート番号の情報表示*/
    #endif
          /*ソケットオープン*/
    sock 
      = socket(PF_INET, SOCK_STREAM, 0);
    if (sock == 
      INVALID_SOCKET) {
        
      fprintf(stderr,"socket() 
      error\n");
        
      WSACleanup();
        return 
      INVALID_SOCKET;
    }
          /*ソケット結合*/
    
      sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = 
      port;
    sockAddr.sin_addr = 
      *((LPIN_ADDR)*lpHost->h_addr_list);
    
      status=connect(sock, (PSOCKADDR)&sockAddr, 
      sizeof(SOCKADDR_IN));
    if (status) 
      {
        fprintf(stderr,"connect() 
      error\n");
        
      closesocket(sock);
        
      WSACleanup();
        return 
      INVALID_SOCKET;
    }
    return 
      sock;
}
      #define sndBufSize 
      100*1024
#define rcvBufSize 1024
      typedef struct 
      {
    char sender[128];      
      /*送信者すなわち自分のメールアドレス*/
    char 
      receiver[128];    /*送信先のメールアドレス*/
    
      char subject[1024];    /*サブジェクト(件名)*/
    
      char body[sndBufSize]; /*メール本体*/
} mail_t;
      //mime変換のためのテーブル      
      0123456789012345678901234567890123456789012345678901234567890123
const 
      char 
      MimeEncodeTable[70]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      //文字列intext(normal)を文字列otext(mime 
      encoded)に変換
//BASE64を利用したMIME変換
void PureMimeEncode(char *intext, 
      char *otext, int len)
{
    unsigned char 
      *p;
    unsigned long int x,x1;
    
      unsigned char tmp[8]={0,0,0,0,0,0,0,0};
    char 
      one[4]="A";
    int add,len1,i,j;
    
      add=0;
    len1=len;
    if (len%3!=0) 
      {
        add= 
      3-(len%3);
        
      len1=len/3*3;
    }
    p=(unsigned 
      char *)intext;
    *otext=0;
    for 
      (i=0; i<len1; i+=3) {
        
      x=(p[0]<<16)+(p[1]<<8)+p[2];
        
      x1=(x>>18)&0x3f; one[0]=MimeEncodeTable[x1]; 
      strcat(otext,one);
        
      x1=(x>>12)&0x3f; one[0]=MimeEncodeTable[x1]; 
      strcat(otext,one);
        
      x1=(x>>06)&0x3f; one[0]=MimeEncodeTable[x1]; 
      strcat(otext,one);
        
      x1=(   x )&0x3f; one[0]=MimeEncodeTable[x1]; 
      strcat(otext,one);
        
      p+=3;
    }
    if (add) 
      {
        for (j=0 ; i<len; 
      i++,j++) tmp[j]=*p++;
        
      x=(tmp[0]<<16)+(tmp[1]<<8)+tmp[2];
        
      x1=(x>>18)&0x3f; one[0]=MimeEncodeTable[x1]; 
      strcat(otext,one);
        
      x1=(x>>12)&0x3f; one[0]=MimeEncodeTable[x1]; 
      strcat(otext,one);
        
      x1=(x>>06)&0x3f; one[0]=MimeEncodeTable[x1]; 
      strcat(otext,one);
        
      x1=(   x )&0x3f; one[0]=MimeEncodeTable[x1]; 
      strcat(otext,one);
    }
    //add=0 
      -> del=0, add=1 -> del=1, add=2 -> del=2
    
      p=otext+strlen(otext)-1;
    for (i=0; i<add; i++) 
      *p--='=';
}
      //ユーザIDuserとパスワードpassからauth文字列(mime(user\0user\0pass))を作る
void 
      makeAuthPlain(char *user, char *pass, char 
      *auth)
{
    int num,i;
    char 
      plain[256];
    
      strcpy(plain,user);
    
      strcat(plain,"\t");
    
      strcat(plain,user);
    
      strcat(plain,"\t");
    
      strcat(plain,pass);
    
      //puts(plain);
    
      num=strlen(plain);
    for (i=0;i<num;i++) if 
      (plain[i]=='\t') plain[i]=0;
    
      PureMimeEncode(plain,auth,num);
}
      typedef struct 
      {
    char smtpserver[128];
    int 
      port;
    char userID[128];
    char 
      passwd[128];
    char authplainstr[128];
} 
      smtp_t;
      void 
      setAuthPlainString(smtp_t *smtp)
{
    
      makeAuthPlain(smtp->userID, smtp->passwd, 
      smtp->authplainstr);
}
      /*SMTPサーバsmtpにメールmailを送る関数 失敗したら0以外を戻す*/
int 
      sendMail(smtp_t *smtp, const char *smtpclient, mail_t 
      *mail)
{
    SOCKET sock;
    
      static char sndBuf[sndBufSize],rcvBuf[rcvBufSize];
    
      setAuthPlainString(smtp);
          
      /*SMTPサーバへの接続とリプライ受信*/
    
      sock=connectSocket(smtp->smtpserver,"secure_smtp",(short 
      int)smtp->port);
    if (sock == INVALID_SOCKET) 
      return 1;
    
      receiveData(sock,rcvBuf,rcvBufSize);
    if 
      ('3'<rcvBuf[0]) {
        
      printf("** ERROR ** 
      %s\n",rcvBuf);
        
      closesocket(sock);
        
      WSACleanup();
        return 
      1;
    }
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("connecting 
      Socket\n");
        
      printf("receiving : %s\n",rcvBuf);
    
      #endif
          
      /*"EHLO"コマンドの送信とリプライ受信*/
    
      /*クライアントの認証に失敗する場合はここの部分にsmtpサーバ名を書く*/
    
      sprintf(sndBuf,"EHLO %s \r\n",smtpclient);
    
      sendData(sock, sndBuf);
    
      receiveData(sock,rcvBuf,rcvBufSize);
    if 
      ('3'<rcvBuf[0]) {
        
      printf("** ERROR ** 
      %s\n",rcvBuf);
        
      closesocket(sock);
        
      WSACleanup();
        return 
      1;
    }
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : 
      %s",sndBuf);
        
      printf("receiving : %s\n",rcvBuf);
    
      #endif
          /*"AUTH 
      PLAIN"コマンドの送信とリプライ受信*/
    sprintf(sndBuf,"AUTH PLAIN 
      %s\r\n",smtp->authplainstr);
    sendData(sock, 
      sndBuf);
    
      receiveData(sock,rcvBuf,rcvBufSize);
    if 
      ('3'<rcvBuf[0]) {
        
      printf("** ERROR ** 
      %s\n",rcvBuf);
        
      closesocket(sock);
        
      WSACleanup();
        return 
      1;
    }
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : 
      %s",sndBuf);
        
      printf("receiving : %s\n",rcvBuf);
    
      #endif
          /*"MAIL 
      FROM"コマンドの送信とリプライ受信*/
    sprintf(sndBuf,"MAIL 
      FROM:<%s>\r\n",mail->sender);
    
      sendData(sock, sndBuf);
    
      receiveData(sock,rcvBuf,rcvBufSize);
    if 
      ('3'<rcvBuf[0]) {
        
      printf("** ERROR ** 
      %s\n",rcvBuf);
        
      closesocket(sock);
        
      WSACleanup();
        return 
      1;
    }
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : 
      %s",sndBuf);
        
      printf("receiving : %s\n",rcvBuf);
    
      #endif
          /*"RCPT 
      TO"コマンドの送信とリプライ受信*/
    /*複数のあて先に同報送信する場合は,RCPT 
      TO"コマンドの送信とリプライ受信をここに並べればよい*/
    sprintf(sndBuf,"RCPT 
      TO:<%s>\r\n",mail->receiver);
    
      sendData(sock, sndBuf);
    
      receiveData(sock,rcvBuf,rcvBufSize);
    if 
      ('3'<rcvBuf[0]) {
        
      printf("** ERROR ** 
      %s\n",rcvBuf);
        
      closesocket(sock);
        
      WSACleanup();
        return 
      1;
    }
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : 
      %s",sndBuf);
        
      printf("receiving : %s\n",rcvBuf);
    
      #endif
          
      /*"DATA"コマンドの送信とリプライ受信*/
    
      sprintf(sndBuf,"DATA\r\n");
    sendData(sock, 
      sndBuf);
    
      receiveData(sock,rcvBuf,rcvBufSize);
    if 
      ('3'<rcvBuf[0]) {
        
      printf("** ERROR ** 
      %s\n",rcvBuf);
        
      closesocket(sock);
        
      WSACleanup();
        return 
      1;
    }
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : 
      %s",sndBuf);
        
      printf("receiving : %s\n",rcvBuf);
    
      #endif
          
      /*本文ヘッダの送信(サブジェクト)*/
    sprintf(sndBuf,"Subject: 
      %s\r\n",mail->subject);
    sendData(sock, 
      sndBuf);
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : %s",sndBuf);
    
      #endif
          
      /*本文ヘッダの送信(「To」行)*/
    sprintf(sndBuf,"To: 
      %s\r\n",mail->receiver);
    sendData(sock, 
      sndBuf);
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : %s",sndBuf);
    
      #endif
          
      /*本文ヘッダの送信(「From」行)*/
    sprintf(sndBuf,"From: 
      %s\r\n",mail->sender);
    sendData(sock, 
      sndBuf);
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : %s",sndBuf);
    
      #endif
          
      /*本文ヘッダの送信(ヘッダ終了の意味の空行)*/
    
      sprintf(sndBuf,"\r\n");
    sendData(sock, 
      sndBuf);
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : %s",sndBuf);
    
      #endif
    
      /*そのほかの本文ヘッダがある場合は本文本体送信前に記述すればよい*/
          
      /*本文本体の送信*/
    
      sprintf(sndBuf,"%s\r\n",mail->body);
    
      sendData(sock, sndBuf);
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : %s",sndBuf);
    
      #endif
          
      /*本文終了マークの送信*/
    
      sprintf(sndBuf,".\r\n");
    sendData(sock, 
      sndBuf);
    
      receiveData(sock,rcvBuf,rcvBufSize);
    if 
      ('3'<rcvBuf[0]) {
        
      printf("** ERROR ** 
      %s\n",rcvBuf);
        
      closesocket(sock);
        
      WSACleanup();
        return 
      1;
    }
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : 
      %s",sndBuf);
        
      printf("receiving : %s\n",rcvBuf);
    
      #endif
          
      /*"QUIT"コマンドの送信とリプライ受信*/
    
      sprintf(sndBuf,"QUIT\r\n");
    sendData(sock, 
      sndBuf);
    
      receiveData(sock,rcvBuf,rcvBufSize);
    if 
      ('3'<rcvBuf[0]) {
        
      printf("** ERROR ** 
      %s\n",rcvBuf);
        
      closesocket(sock);
        
      WSACleanup();
        return 
      1;
    }
    #ifdef REQUEST_INFO 
      /*情報要求がある場合(学習のため)*/
        
      printf("sending   : 
      %s",sndBuf);
        
      printf("receiving : %s\n",rcvBuf);
    
      #endif
          
      closesocket(sock);
    
      WSACleanup();
    return 0;
}
      int 
      main()
{
    mail_t mymail;
    
      smtp_t smtp;
    strcpy(mymail.subject,"test mail"); 
      /*メールのサブジェクトの設定*/
    strcpy(mymail.body,"test mail 
      body  Hello from Tokyo."); /*メールの本文の設定*/
    
      strcpy(mymail.sender,mymailaddress); /*送信者アドレスの設定*/
    
      strcpy(mymail.receiver,mymailaddress); 
      /*受信者アドレスの設定*/
    
      strcpy(smtp.smtpserver,smtpservername); 
      /*smtpサーバ名の設定*/
    smtp.port=port; 
      /*ポート番号のセット*/
    strcpy(smtp.userID,userID); 
      /*認証用ユーザIDの設定*/
    strcpy(smtp.passwd,passwd); 
      /*パスワードの設定*/
    sendMail(&smtp, smtpclientname, 
      &mymail);
    return 0;
}