// Mail send sample (with SMTP auth)
int send( char *adrs, char type, char *rpt )
{
  char soc,stat;
  long ip;
  if( !*adrs ) return (-1);
  MailTo = MemoryAlloc( StrLen( adrs ) + 1 );
  StrCpy( MailTo, adrs );
  if( (soc = CreateSocket( 1 )) < 0 ) return (-1);
  if( (ip = GetHostByName( Server )) == 0 ) return (-1);
  if( Connect( soc, ip, 25 ) < 0 ) return (-1);
//  if( Connect( soc, ip, 587 ) < 0 ) return (-1);
  SmtpState = 1;
  for(;;)
  {
    stat = Mail::SmtpHandler( soc, type, rpt );
    if( stat < 0 || stat == 1 ) break;
    SystemSleep();
  }
  CloseSocket( soc );
  return 0;
}

// Send sub
char SendStr( char s, char *b )
{
  if( Write( s, b, StrLen( b ) ) < 0 ) return -2;
  WaitWriteComplete( s );
  return 0;
}

// SMTP handler (with SMTP auth)
char SmtpHandler( char soc, char type, char *rpt )
{
  int len;
  char *recbuf,*sendbuf;
  char *MailFrom = "PetSetRadio@hamayan.ddo.jp";
  char *MailName = "PetSetRadio";
  char *Sub = "Alert Messages from Pet Set Radio.";
  char *SmtpName = "";
  char *SmtpPass = "";
//  char *SmtpName = "";
//  char *SmtpPass = "";
  if( SmtpState )
  {
    if( ( len = Read( soc, 2000 ) ) < 0) return (-1);
    recbuf = GetReceiveBuffer( soc, 1 );
//    PrStr( recbuf );
    if( *recbuf != '3' && *recbuf != '2' )
    {
      MemoryFree( recbuf );
      return -4;
    }
  }
  MemoryFree( recbuf );
  switch( SmtpState )
  {
    case 1:
      if( SendStr( soc,"HELO hamayan.ddo.jp\r\n" ) < 0 ) return -2;
      if( *SmtpName ) SmtpState++;
      else SmtpState = 6;
      break;
    case 2:
      if( SendStr( soc, "AUTH LOGIN\r\n" ) < 0 ) return -2;
      SmtpState++;
      break;
    case 3:
      sendbuf = MemoryAlloc( 128 );
      Mail::Enc64( sendbuf, SmtpName );
      StrCat( sendbuf, "\r\n" );
      if( SendStr( soc, sendbuf ) < 0 ) return -2;
      MemoryFree( sendbuf );
      SmtpState++;
      break;
    case 4:
      sendbuf = MemoryAlloc( 128 );
      Mail::Enc64( sendbuf, SmtpPass );
      StrCat( sendbuf, "\r\n" );
      if( SendStr( soc, sendbuf ) < 0 ) return -2;
      MemoryFree( sendbuf );
      SmtpState++;
      break;
    case 5:
      if( SendStr( soc, "RSET\r\n" ) < 0 ) return -2;
      SmtpState++;
      break;
    case 6:
      sendbuf = MemoryAlloc( StrLen( MailFrom ) + 15 );
      StrCpy( sendbuf, "MAIL FROM:<" );
      StrCat( sendbuf, MailFrom );
      StrCat( sendbuf, ">\r\n");
      if( SendStr( soc, sendbuf ) < 0 ) return -2;
      MemoryFree( sendbuf );
      SmtpState++;
      break;
    case 7:
      sendbuf = MemoryAlloc( StrLen( MailTo ) + 13 );
      StrCpy( sendbuf, "RCPT TO:<" );
      StrCat( sendbuf, MailTo );
      StrCat( sendbuf, ">\r\n" );
      if( SendStr( soc, sendbuf ) < 0 ) return -2;
      MemoryFree( sendbuf );
      SmtpState++;
      break;
    case 8:
      if( SendStr( soc, "DATA\r\n" ) < 0 ) return -2;
      SmtpState++;
      break;
    case 9:
      sendbuf = MemoryAlloc( StrLen( MailTo ) + 8 );
      StrCpy( sendbuf, "To:<" );
      StrCat( sendbuf, MailTo );
      StrCat( sendbuf, ">\r\n" );
      if( SendStr( soc, sendbuf ) < 0 ) return -2;
      MemoryFree( sendbuf );
      sendbuf = MemoryAlloc( StrLen( MailName ) + StrLen( MailFrom ) + 12 );
      StrCpy( sendbuf, "From: " );
      StrCat( sendbuf, MailName );
      StrCat( sendbuf, " <" );
      StrCat( sendbuf, MailFrom );
      StrCat( sendbuf, ">\r\n" );
      if( SendStr( soc, sendbuf ) < 0 ) return -2;
      MemoryFree( sendbuf );
      sendbuf = MemoryAlloc( StrLen( Sub ) + 14 );
      StrCpy( sendbuf, "Subject: " );
      StrCat( sendbuf, Sub );
      StrCat( sendbuf, "\r\n\r\n" );
      if( SendStr( soc, sendbuf ) < 0 ) return -2;
      MemoryFree( sendbuf );
      switch( type )
      {
        case 'e' :
          if( SendStr( soc, "Caution! A serious accident occurred.\r\nPlease contact it as soon as possible.\r\n" ) < 0 ) return -2;
          break;
        case 'a' :
          if( SendStr( soc, "Warnig! Can't receive a radio.\r\n" ) < 0 ) return -2;
          break;
        case 'l' :
          if( SendStr( soc, "Warnig! Low battery detected.\r\nA Charge is needed.\r\n" ) < 0 ) return -2;
          if( SendStr( soc, rpt ) < 0 ) return -2;
          break;
        case 'w' :
          if( SendStr( soc, "Report! A wireless device waked up.\r\n" ) < 0 ) return -2;
          break;
        case 'p' :
          if( SendStr( soc, "Report! A periodical report.\r\n" ) < 0 ) return -2;
          if( SendStr( soc, rpt ) < 0 ) return -2;
          break;
      }
      if( SendStr( soc, "\r\n.\r\n" ) < 0 ) return -2;
      SmtpState++;
      break;
    case 10:
      if( SendStr( soc, "QUIT\r\n" ) < 0 ) return -2;
      SmtpState++;
      break;
    case 11:
      SmtpState = 0;
      return 1;
  }
  return 0;
}

// Number to BASE64
char Get64( char c )
{
  c &= 63;
  if( c < 26 ) return c + 65;
  if( c < 52 ) return c + 71;
  if( c < 62 ) return c - 4;
  if( c == 62 ) return '+';
  return '/';
}

// BASE64 to number
char Conv64( char c )
{
  if( c == '=' ) return 0;
  if( c == '+' ) return 62;
  if( c == '/' ) return 63;
  if( c < 58 ) return c + 4;
  if( c < 91) return c - 65;
  if( c < 123 ) return c - 71;
}

// String to BASE64
void Enc64( char *dst, char *src )
{
  char get,put;
  for(;;)
  {
    if( !src[ get ]) break;
    dst[ put ] = Get64( src[ get ] >> 2 );
    if( !src[ get + 1 ] )
    {
      dst[ put + 1 ] = Get64( ( src[ get ] & 3 ) << 4 );
      dst[ put + 2 ] = '=';
      dst[ put + 3 ] = '=';
      dst[ put + 4 ] = 0;
      break;
    }
    dst[ put + 1 ] = Get64((( src[ get ] & 3 ) << 4 ) + ( src[ get + 1 ] >> 4 ));
    if( !src[ get + 2 ])
    {
      dst[ put + 2 ] = Get64(( src[ get + 1 ] & 15 ) << 2);
      dst[ put + 3 ] = '=';
      dst[ put + 4 ] = 0;
      break;
    }
    dst[ put + 2 ] = Get64((( src[ get + 1 ] & 15 ) << 2 ) + ( src[ get + 2 ] >> 6 ));
    dst[ put + 3 ] = Get64( src[ get + 2 ] & 63 );
    dst[ put + 4 ] = 0;
    get += 3;
    put += 4;
  }
}

// BASE64 to string
void Dec64( char *dst, char *src )
{
  char get,put,c1,c2,c3;
  for(;;)
  {
    if( !src[ get ]) break;
    c1 = Conv64( src[ get++ ]) << 2;
    c2 = Conv64( src[ get++ ]);
    c1 |= ( c2 >> 4 ) & 3;
    c3 = Conv64( src[ get++ ] );
    c2 = c2 << 4 | (( c3 >> 2 ) & 15 );
    c3 = c3 << 6 | Conv64( src[ get++ ] );
    dst[ put++ ] = c1;
    if( c2 )
    {
      dst[ put++ ] = c2;
      if( c3 ) dst[ put++ ] = c3;
    }
  }
  dst[ put ] = 0;
}
