CGIを経由したメール送信

  1. 目的


     電子メールは、携帯電話などでも利用でき、優れた情報発信ツールです。アプレットからSMTPプロトコルでメールを送信できますが、この方法では、SMTPサーバーを指定する必要があるため、「どこでも無設定でメール送信」ができません。しかし、CGI を経由したメール送信は、web のサーバーが利用できるため、SMTPサーバーの設定が不要です。
     ここでは、アプレットを利用しCGI を経由した、メールの送信プログラムを紹介します。

  2. URLコネクション


    1. URL接続

       アプレットから、CGIに接続するには、次のようにURLコネクションを利用します。
            URL url=new URL("http://150.42.41.129/cgi-bin/tool/sendmail.cgi");
            URLConnection uc = url.openConnection();
            uc.setDoOutput(true);
            uc.setUseCaches(false);
      URLクラスのインスタンスを、サーバーの CGI を指定して生成します。これから、url.openConnection(); でuc を作成し、setDoOutput() で、出力モードを設定します。これで、
           PrintWriter pw = new PrintWriter(uc.getOutputStream());
      で、PrintWriterクラスの pw を生成すると、pwから CGI にURLエンコードしたパラメータが送出されます。この文字列は、html のFORM タグで、入力した情報を送信する場合と同じです。

    2. 情報の送信

      メールの、送信者、宛先、タイトル(サブジェクト)、本文、などが TextField に入力されている場合、送信形式は次のようになります(CGIエンコード形式になります)。
      String data="from="+textFieldFrom.getText()+"&to="+textFieldTo.getText()
         +"&title="+textFieldsbj.getText()+"&msg="+textFieldmsg.getText();
      form= の from が送信者アドレスを示すキーで、CGI側でも、この名前を利用して情報を取り出します。したがって、パラメータを送る順番には意味がありません。 & はパラメータを接続(分離する)する 記号になります。スペースなどの特殊記号、漢字などは別の文字に変換され送ります。

    3. 情報の入力
       CGIから送信される文字列は、
            BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));
              String line="";
              String answer= "";
              while((line = br.readLine()) != null){
                  answer += line + "\n";
                  //System.out.println(answer);
              }
      で受け取ることができます。CGIの送信文字は、ページを記述するhtml 文書になりますが、ここでは、単に文字列として受け取ることになります。

  3. CGI


    1. CGI

       ここではCGIの、詳細な説明をしません(「自学」ページの「プログラミング」>Webプログラミング>CGIを参照して下さい)。CGI はWEBサーバーと連携し、webサーバーから情報を受け取り、指定された処理を行う手法です。CGI 専用の言語やシステムがあるわけではありません。ここでは、Perl 言語を利用した、メール送信CGIを利用します。

    2. メール送信

       実際のメール送信は、先頭のURLで指定した、CGI:ここでは sendmail.cgi が行います。したがって、ここでのアプレットのプログラムはCGIに必要な情報を送る一般的な手法として利用できます。
       sendmail.cgi のメールの送信部分を紹介します。メール送信で大切なことは送信する文字符号の調整です。本文は Jis コードに変換します(jcode'jis() )。サブジェクトはJISコードに変換後、MIME(マイム)形式に変換します(mimeencode)。MIMEは英字だけでなく、他の文字コードや画像などを文字コードに変換する方法を定めています。

       my $SENDMAIL = "/usr/lib/sendmail";  
      
       $subject = mimeencode( jcode'jis($FORM{'title'}) );
        $message=$FORM{'msg'};
        $message = jcode'jis($message);
        $from = $FORM{'from'};
        $to = $FORM{'to'};
        
        $from =~ s/@/\@/;
        open MAIL,"|$SENDMAIL -t -f $from" || &error("メール送信失敗・・・");
        print MAIL "Subject: $subject\n";
        print MAIL "To: $to\n";
        print MAIL "\n";
      
        print MAIL "$message\n";
        close MAIL;
        }
       実際のメール送信は、open MAIL 以後で行います。openはファイル(javaの場合ストリームの概念に対応します)形式で、指定したアプリケーション (この場合、/usr/lib/sendmail) に、 print MAIL でデータを流し込むことができます。
       ここで、open の中で -f で送信者アドレスを指定しています。多くの場合、open後
       print MAIL "From: $from\n"
      で、設定するのですが、ここで利用している sendmail はコマンド内で設定しないと送信してくれません。
       $from =~ s/@/\@/;
      は、送信者アドレス:from に含まれる @ がPerlでは特殊な意味で解釈されるため、これを避けるためのいわゆる エスケープシーケンスです。 C言語で \n を改行文字として扱うのと同じで、Perl では、\@ が @ の文字と解釈されます。

  4. ソース


    1. アプレット

       以下に、送信ボタンをおしたときURL接続部分を紹介します。全体はこちらを参照して下さい。
          void buttonSend_actionPerformed(ActionEvent e) {
          try{
            URL url=new URL("http://150.42.41.129/cgi-bin/tool/sendmail.cgi");
            URLConnection uc = url.openConnection();
            uc.setDoOutput(true);
            uc.setUseCaches(false);
            System.out.println("connected?");
      
             PrintWriter pw = new PrintWriter(uc.getOutputStream());
             String data="from="+textFieldFrom.getText()+"&to="+textFieldTo.getText()
                 +"&title="+textFieldsbj.getText()+"&msg="+textFieldmsg.getText();
             String postdata=data;
             System.out.println("send:"+postdata);
            pw.print(postdata);
            pw.flush();
            pw.close();
      
            BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));
              String line="";
              String answer= "";
              while((line = br.readLine()) != null){
                  answer += line + "\n";
                  //System.out.println(answer);
              }
            System.out.println(answer);
            br.close();
          }
          catch(Exception ex){
            ex.printStackTrace();
          }
        }
      }

    2. CGI

       sendmail.cgi のソースを紹介します。このファイルを CGI の置き場所 cgi-bin (webサーバーの設定で定まります)の下に、
      tool/sendmail.cgi として配置します。第三者に対する 実行属性 が必要です。ここでは、文字変換などに、三種のライブラリを利用しています。ネットから、ダウンロード可能だと思います。
       require "./mimew.pl"; require "./jcode.pl"; use CGI_Lite;

      #!/usr/bin/perl
      # first sample
      use strict;
      
      require "./mimew.pl";
      require "./jcode.pl";
      use CGI_Lite;
      
      my $SENDMAIL = "/usr/lib/sendmail";
      my $PLATFORM = 'Unix';
      
      # $ENV{'REQUEST_METHOD'}='GET';
      # $ENV{'QUERY_STRING'}='from=web@chukyo-u.ac.jp&to=yt7m-itu@asahi-net.or.jp&msg=hello&title=test';
      
      #main
      my ($from,$to,$message,$subject,%FORM);
      
      
       &decode();
       &send_mail();
       &showPage("送信完了しました<br> . $from . $to.<BR>");
        #送信完了を知らせるページを作成する
      
      
      sub decode {
      
        my ($buffer,@pairs,$pair);
        if ($ENV{'REQUEST_METHOD'} eq 'POST') {
          read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
        } else { $buffer = $ENV{'QUERY_STRING'}; }
      
        @pairs = split(/&/, $buffer);
        foreach $pair (@pairs) {
          my ($key,$value);
          ($key,$value) = split(/=/, $pair);
          $FORM{$key} = $value;
        }
      
      }
      
      #------------#
      # メール送信 #
      #------------#
      
      sub send_mail{
      
        $subject = mimeencode( jcode'jis($FORM{'title'}) );
        $message=$FORM{'msg'};
        $message = jcode'jis($message);
        $from = $FORM{'from'};
        $to = $FORM{'to'};
      
        #open MAIL,"|$SENDMAIL -t  -f mito\@ccad.sccs.chukyo-u.ac.jp" || &error("メール送信失敗・・・");
        
        #$from = "mito\@sccs.chukyo-u.ac.jp";
        $from =~ s/@/\@/;
        open MAIL,"|$SENDMAIL -t -f $from" || &error("メール送信失敗・・・");
      
        #print MAIL "From: mito\@ccad.sccs.chukyo-u.ac.jp\n";
        #print MAIL "From: $from\n";
        print MAIL "Subject: $subject\n";
        print MAIL "To: $to\n";
        print MAIL "\n";
      
        print MAIL "$message\n";
        close MAIL;
        }
      
      sub showPage{
      
        print qq(Content-type: text/html;charset=Shift_JIS\n\n);
        print qq(<HTML><HEAD><TITLE>message</TITLE><BODY>);
        print @_[0];
        print qq( 戻るボタン);
        print qq(</BODY></HTML>); 
      
      }
      
      sub error{
        print qq(Content-type: text/html;charset=Shift_JIS\n\n);
        print qq(<HTML><HEAD><TITLE>message</TITLE><BODY>);
        print @_[0];
        print qq( 送信できません);
        print qq(</BODY></HTML>); 
        exit(0);
      }

  5. 実行


    1. 実行条件

      下のアプレットから送信します。本文、タイトルが漢字が利用できます。送信者に対する漢字表示機能はありません。
      実行には以下の条件が必要です。
       サーバーに CGI が必要です。
       アプレットはCGIにあるサーバー上から実行する必要があります。
      したがって、アプレットをコンパイルしてローカルで実行しても、セキュリティー違反になり、送信できません。かならず、アプレットを cgi のあるサーバーにアップロードしてから実行する必要があるます。

    2. 実行

       fromのメールアドレスはSMTPサーバーと同一ドメイン名とする必要があります(登録済みのアカウントが望ましい)。送信の確認には、メールソフトを利用してください。