• ベストアンサー

ファイル添付有メールフォーム

画像ファイルを添付してメールで受け取れるフォームを作成しているのですが、添付のボタン等も出来上がり、 いざ送信すると普通に送信されましたのメッセージが出るので、一安心と思いメールを開くと、パス名だけが 入力されているだけで添付ファイルが送られません。これは作成ミスなのでしょうか?それともCGIが未対応 なのでしょうか?ちなみにCGIはホームページビルダー12についていたCGIを使用しています。 もしCGIの問題であれば、フリーでダウンロードできるサイトはありますでしょうか? 分かる方宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • okmotokun
  • ベストアンサー率59% (92/155)
回答No.6

>でもメールが一向に届きません。あとはフォーム側に問題があるのでしょうか? メール送信のスクリプトは書いたんですか。 メール送信部分を含めてサンプルスクリプトを貼り付けておきますから参考にしてください。 #!/usr/bin/perl if($ENV{'CONTENT_LENGTH'}){ #▼ 1=添付ファイル許可、2=拒否 $attach=1; #▼ 添付を許可する拡張子(任意) @attach_ext=('gif','jpeg','png'); #------------------------------------------------------------- # 送信方法が「POST」のデータ #------------------------------------------------------------- binmode STDIN; read(STDIN,$query,$ENV{'CONTENT_LENGTH'}); if($ENV{'CONTENT_TYPE'}=~/multipart\/form-data; boundary=(.+)/i){ #------------------------------------------------------------- # 送信形式が「multipart/form-data」のデータ #------------------------------------------------------------- $boundary=$1; foreach(split(/\-+$boundary\-*\x0D*\x0A*/,$query)){ ($header,$val)=split(/\x0D\x0D|\x0A\x0A|\x0D\x0A\x0D\x0A/,$_,2); $header=~s/^(\x0D\x0A|\x0D|\x0A)+//; $val=~s/(\x0D\x0A|\x0D|\x0A)$//; if($header=~/ name="(.+?)"/i&&$val){ $key=$1; if($header=~/filename="(.+)"/){ next unless($attach&&$val); ($filename=$1)=~s,.+[\\/:],,; if($header=~/Content-Type:\s*([^\s]+)/i){ $attachtype=$1; if(@attach_ext){ for(@attach_ext){if($attachtype=~/$_/){$attach=2}} $attach-=1} } if($attach){$attach=$val;$FORM{$key}=$filename; #------------------------------------------------------------- # 添付ファイルの保存(保存不要の場合は以下3行をコメントアウト) #------------------------------------------------------------- open(FILE,">$filename");binmode FILE; print FILE $val; close FILE; }else{$filename=""} }else{ #------------------------------------------------------------- # 添付ファイル以外のデータを %FORM に代入 #------------------------------------------------------------- ($FORM{$key}=$val)=~s/(\x0D\x0A|\x0A|\x0D)/\n/sig; } } } $query=""; } } if($ENV{'QUERY_STRING'}){ #------------------------------------------------------------- # 送信方法が「GET」のデータ #------------------------------------------------------------- if($query){$query.='&'} $query.=$ENV{'QUERY_STRING'}; } if($query){ #------------------------------------------------------------- # 送信形式が「multipart/form-data」以外のデータを %FORM に代入 #------------------------------------------------------------- for(split(/&/,$query)){ ($key,$val)=split(/=/); $val=~s/(%0D%0A|%0A|%0D)/\n/g; $val=~s/<[^>]+>//sg; $val=~s/\+/ /sg; ($FORM{$key}=$val)=~s/%([A-F0-9][A-F0-9])/pack("C",hex($1))/ige; } } #------------------------------------------------------------- # メール送信 #------------------------------------------------------------- #▼ メール題名 $subject=$FORM{'subject'}; #▼ メール本文 $message=$FORM{'comment'}; #▼ 送信先アドレス(複数の場合はコンマ区切り) $mailto='麻生 <asou@mail.jp>,fukuda@mail.jp (福田),abe@mail.com'; #▼ 送信者アドレス $from='サポート <support@mail.co.jp>'; #▼ 返信先アドレス(任意) $replyto='返信 <webmaster@mail.co.jp>'; #▼ 送信完了後のリダイレクト先 $back=''; #▼ sendmaiコマンドパス $sendmail='/usr/sbin/sendmail'; #※メールアドレスは下記いずれかの書式で指定する # accunt@servername.tld # 名前 <accunt@servername.tld> # account@servername.tld (名前) if($sendmail&&$subject&&$mailto&&$from){ sendmail(); if($back){ print "Location: $back\n\n" }else{ $status=~s/\0/\n/g; if($filename){if($attachtype=~/image/){$atlink=qq(<img src="$filename">)}else{$atlink=qq(<a href="$filename">)}} print <<PF; cache-control: private, max-age=0 pragma: no-cache\ncontent-type:text/html; charset=Shift_JIS\n <html> <h1>送信完了</h1><pre> ありがとうございます。 メール送信を完了しました。 ---------------------------------- Subject: $subject Message: $message Status: 0:送信完了、-1:送信失敗 $status $filename $atlink </html> PF } exit()} sub sendmail{ require 'jcode.pl'; if($from=~s/([-+\w.]+\@[-\w.]+)//){$fromaddr=$1; $from=~s/^\s+|"|\(|\)|<|>|\s+$//g; $from=$from?base64($from)." <$fromaddr>":"<$fromaddr>"; } if($replyto=~s/([-+\w.]+\@[-\w.]+)//){$replyaddr=$1; $replyto=~s/^\s+|"|\(|\)|<|>|\s+$//g; $replyto=$replyto?base64($replyto)." <$replyaddr>":"<$replyaddr>"; } foreach$to(split(/,/,$mailto)){ if($to=~s/([-+\w.]+\@[-\w.]+)//){$toaddr=$1; $to=~s/^\s+|"|\(|\)|<|>|\s+$//g; $to=$to?base64($to)." <$toaddr>":"<$toaddr>"; } if(open(MAIL,"| $sendmail -t -f $fromaddr")){ print MAIL "To: $to\n"; print MAIL "From: $from\n"; if($replyto){print MAIL "Reply-To: $replyto\n"} print MAIL "Subject: ".base64($subject)."\n"; print MAIL "MIME-Version: 1.0\n"; if($attach&&$attachtype){ $boundary='----=_webmastertool.jp_'.time(); print MAIL "Content-Type: multipart/mixed;\n\tboundary=\"$boundary\"\n"; }else{ print MAIL "Content-type: text/plain; charset=ISO-2022-JP\n"; print MAIL "Content-Transfer-Encoding: 7bit\n"; } print MAIL "X-Mailer: webmastertool.jp_f2mail.cgi v0.1\n\n"; if($attach&&$attachtype){ print MAIL "This is a multi-part message in MIME format.\n\n"; if($message){ print MAIL "--$boundary\nContent-Type: text/plain;\n\tcharset=\"iso-2022-jp\"\nContent-Transfer-Encoding: 7bit\n\n" } } if($message){ foreach(split(/\n/,$message)){ jcode::convert(*_,'jis','sjis'); print MAIL $_,"\n"; } print MAIL "\n"; } if($attach&&$attachtype){ print MAIL "--$boundary\nContent-Type: $attachtype;\n\tname=\"$filename\"\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment;\n\tfilename=\"$filename\"\n\n"; print MAIL b64enc($attach)."\n"; print MAIL "--$boundary--\n\n" } close MAIL;$status.="0:$toaddr\0"}else{$status.="-1:$toaddr\0"}} } sub base64{ local($subj)=shift; return $subj unless($subj=~/\W/); jcode::convert(*subj,'jis','sjis'); $subj=~s/\x1b\x28\x42/\x1b\x28\x4a/g; $subj='=?iso-2022-jp?B?'.b64enc($subj,'sj').'?='; $subj } sub b64enc{ local($ch)='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; local($x,$y,$z,$i); $x=unpack("B*",$_[0]); for($i=0;$y=substr($x,$i,6);$i+=6){ $z.=substr($ch,ord(pack("B*","00".$y)),1); if(length($y)==2){$z.='=='}elsif(length($y)==4){$z.='='} } $z=~s/(.{76})(?!\n)/$1\n/g unless($_[1]); $z; } __END__

その他の回答 (5)

  • okmotokun
  • ベストアンサー率59% (92/155)
回答No.5

>添付ファイルはキチンと保存を確認しましたので、# %FORM に代入したデータを画面に表示してみる以下のコードを 自分なりに変えてみたのですが、HTTP500 内部サーバーエラーが出てきてしまいます。 何をどうしたら、内部サーバーエラーが出たのか書いてありませんが、多分、メールフォームのページにデータを入力して送信したら、ということでしょう。 そうならば当然、500エラーになります。 CGIの仕組みは、クライアントからのアクションを受け取って、サーバー側でそれを処理して、クライアントに返すものです。 このプログラムは構文エラーはありませんが(BullRiderさんがどういうプログラムを作ろうとしているのかちょっと分からなくなってきましたが)、クライアントに何も返していないから500エラーになります。 フォームから受信したデータの処理をして、最後に $back変数に定義したページにリダイレクトするなら、最後に print "location: $back\n\n";exit(); というようなのを書いておかないと、途中テストはできません。

BullRider
質問者

補足

ご回答ありがとうございます。 説明不足が多々あり申し訳ありません。。ご察しの通り送信ボタンにより送信すると500エラーが発生しておりました。 print "location: $back\n\n";exit(); コチラを追加する事によって「送信しました」の画面にまでこぎ着ける事ができました。 でもメールが一向に届きません。あとはフォーム側に問題があるのでしょうか?

  • okmotokun
  • ベストアンサー率59% (92/155)
回答No.4

メールフォームから送信したデータは正しくパースされ、添付ファイルは保存されましたか。 確認できたら、 #------------------------------------------------------------- # %FORM に代入したデータを画面に表示してみる #------------------------------------------------------------- 以下は不要ですから削除して、ここにメール送信のためのコードを書いてください。

BullRider
質問者

補足

長くお付き合い非常に感謝します。 添付ファイルはキチンと保存を確認しましたので、# %FORM に代入したデータを画面に表示してみる以下のコードを 自分なりに変えてみたのですが、HTTP500 内部サーバーエラーが出てきてしまいます。全体をこんな風に変更してみました。 #!/usr/bin/perl if($ENV{'CONTENT_LENGTH'}){ #------------------------------------------------------------- # 送信方法が「POST」のデータ #------------------------------------------------------------- binmode STDIN; read(STDIN,$query,$ENV{'CONTENT_LENGTH'}); if($ENV{'CONTENT_TYPE'}=~/multipart\/form-data; boundary=(.+)/i){ #------------------------------------------------------------- # 送信形式が「multipart/form-data」のデータ #------------------------------------------------------------- $boundary=$1; foreach(split(/\-+$boundary\-*\x0D*\x0A*/,$query)){ ($header,$val)=split(/\x0D\x0D|\x0A\x0A|\x0D\x0A\x0D\x0A/,$_,2); $header=~s/^(\x0D\x0A|\x0D|\x0A)+//; $val=~s/(\x0D\x0A|\x0D|\x0A)$//; if($header=~/ name="(.+?)"/i&&$val){ $key=$1; if($header=~/filename="(.+)"/){ #------------------------------------------------------------- # 貼付ファイルの保存 #------------------------------------------------------------- ($filename=$1)=~s,.+[\\/:],,; $FORM{$key}=$filename; open(FILE,">$filename");binmode FILE; print FILE $val; close FILE; }else{ #------------------------------------------------------------- # 貼付ファイル以外のデータを %FORM に代入 #------------------------------------------------------------- ($FORM{$key}=$val)=~s/(\x0D\x0A|\x0A|\x0D)/\n/sig; } } } $query=""; } } if($ENV{'QUERY_STRING'}){ #------------------------------------------------------------- # 送信方法が「GET」のデータ #------------------------------------------------------------- if($query){$query.='&'} $query.=$ENV{'QUERY_STRING'}; } if($query){ #------------------------------------------------------------- # 送信形式が「multipart/form-data」以外のデータを %FORM に代入 #------------------------------------------------------------- for(split(/&/,$query)){ ($key,$val)=split(/=/); $val=~s/(%0D%0A|%0A|%0D)/\n/g; $val=~s/<[^>]+>//sg; $val=~s/\+/ /sg; ($FORM{$key}=$val)=~s/%([A-F0-9][A-F0-9])/pack("C",hex($1))/ige; } } # 送信先メールアドレス $mailto = 'aaaa@yahoo.co.jp'; # 添付メールを許可する # 0 : no # 1 : yes $attach = 1; # 添付メール許可のとき添付ファイルの「拡張子」を指定する場合 # → 例 (ドットなしで記述) : @pmt_ext = ('gif', 'jpg', 'jpeg', 'png'); # → すべての拡張子をOKにするときは、@pmt_ext = (); とします @pmt_ext = ('gif', 'jpg', 'jpeg', 'png', 'bmp'); # 送信後の形態 # 0 : 完了メッセージを出す. # 1 : 戻り先 ($back) へ自動ジャンプさせる. $reload = 0; # 送信後の戻り先【URLパス】 # → http://から記述する $back = 'http://www.aaaa.com/'; # メール送信形式 # 1 : sendmail送信(sendmailが利用可能なサーバ) # 2 : IO:Socketモジュール送信(ソケット関連のモジュールが利用可能なサーバ) $send_type = 1; ## sendmail送信のとき ## # sendmailのパス $sendmail = '/usr/lib/sendmail';

  • okmotokun
  • ベストアンサー率59% (92/155)
回答No.3

1ヵ所間違えました。 サンプルコードの $ENV{'CONTENT_TYPE'}='GET'; は $ENV{'CONTENT_TYPE'}||='GET'; です。

BullRider
質問者

補足

詳しいお返事本当にありがとうございます。すごく勉強させていただきました。 今回のサンプルcgiを見てどういう事なのか何となく分かってきた気がします。 ただこのサンプルの場合送信先のメールアドレスはどこに入力すれば良いのでしょう? #!/usr/bin/perl if($ENV{'CONTENT_LENGTH'}){ $mailto = 'aaaa@yahoo.co.jp'; $subject = 'Registration request'; のような感じでよろしいのでしょうか? 何度も質問ばかりですみません。。宜しくお願いします。

  • okmotokun
  • ベストアンサー率59% (92/155)
回答No.2

フォームに入力されたデータは、送信形式(enctype)が application/x-www-form-urlencode の場合は、name=%エンコードされた入力値 が & で連結されて送信されてきますが、 送信形式が multipart/form-data の場合は入力値、添付ファイルのデータはエンコードされず、入力値ごとに Content-Disposition: form-data; name="xxxx" というヘッダが付けられます。 ※ヘッダとデータの1セットをパートといいます。 ※添付ファイルパートのヘッダには、filename="xxxx" と、ファイルの種類を示す Content-Type: xxxx/xxxx が付加されます。 ※ヘッダとデータ2個の改行コードで区切られています。 各パートは環境変数 $ENV{'CONTENT_TYPE'}にセットされた "boundary"という境界文字列で区切られて送信されてきます。 したがって、データを受け取ったCGIスクリプト側では、 (1)まず、全体を各パートに boundary ごとに区分けし (2)次に、各パートをヘッダ部とデータ部に分け (3)そして、ヘッダ部のname属性値をキーにして、変数にデータ部を代入する という処理をします。これを フォームデータのパース といいます。 添付ファイルがある場合は、ヘッダに付けられた Content-Type属性に応じて処理します。 なお、ヘッダのfilename属性値は、クライアントのブラウザによって、ファイル名だけの場合、ローカルパス付きの場合があります。 【サンプル】 #!/usr/bin/perl if($ENV{'CONTENT_LENGTH'}){ #------------------------------------------------------------- # 送信方法が「POST」のデータ #------------------------------------------------------------- binmode STDIN; read(STDIN,$query,$ENV{'CONTENT_LENGTH'}); if($ENV{'CONTENT_TYPE'}=~/multipart\/form-data; boundary=(.+)/i){ #------------------------------------------------------------- # 送信形式が「multipart/form-data」のデータ #------------------------------------------------------------- $boundary=$1; foreach(split(/\-+$boundary\-*\x0D*\x0A*/,$query)){ ($header,$val)=split(/\x0D\x0D|\x0A\x0A|\x0D\x0A\x0D\x0A/,$_,2); $header=~s/^(\x0D\x0A|\x0D|\x0A)+//; $val=~s/(\x0D\x0A|\x0D|\x0A)$//; if($header=~/ name="(.+?)"/i&&$val){ $key=$1; if($header=~/filename="(.+)"/){ #------------------------------------------------------------- # 貼付ファイルの保存 #------------------------------------------------------------- ($filename=$1)=~s,.+[\\/:],,; $FORM{$key}=$filename; open(FILE,">$filename");binmode FILE; print FILE $val; close FILE; }else{ #------------------------------------------------------------- # 貼付ファイル以外のデータを %FORM に代入 #------------------------------------------------------------- ($FORM{$key}=$val)=~s/(\x0D\x0A|\x0A|\x0D)/\n/sig; } } } $query=""; } } if($ENV{'QUERY_STRING'}){ #------------------------------------------------------------- # 送信方法が「GET」のデータ #------------------------------------------------------------- if($query){$query.='&'} $query.=$ENV{'QUERY_STRING'}; } if($query){ #------------------------------------------------------------- # 送信形式が「multipart/form-data」以外のデータを %FORM に代入 #------------------------------------------------------------- for(split(/&/,$query)){ ($key,$val)=split(/=/); $val=~s/(%0D%0A|%0A|%0D)/\n/g; $val=~s/<[^>]+>//sg; $val=~s/\+/ /sg; ($FORM{$key}=$val)=~s/%([A-F0-9][A-F0-9])/pack("C",hex($1))/ige; } } #------------------------------------------------------------- # %FORM に代入したデータを画面に表示してみる #------------------------------------------------------------- foreach$key(keys %FORM){ if($boundary&&$key=~/file/){$indata.="【\$$key】<br><a href=$FORM{$key}>$FORM{$key}</a>\n"} else{$indata.="【\$$key】<br>$FORM{$key}\n"} $indata.='-'x(50)."\n"; } $ENV{'CONTENT_TYPE'}=~s/;.+//; if($ENV{'CONTENT_TYPE'}=~/text\/plain/){$indata=$query.'-'x(50)} $ENV{'CONTENT_TYPE'}='GET'; print <<PF; cache-control: private, max-age=0 pragma: no-cache\ncontent-type:text/html; charset=Shift_JIS\n <html> <head> <title>FORM TEST</title> </head> <body> <h1>$ENV{'CONTENT_TYPE'}</h1> <span style="font-size:18px;line-height:20px"> <pre> $indata </pre> </body> </html> PF exit();

  • okmotokun
  • ベストアンサー率59% (92/155)
回答No.1

フォームの enctype属性デフォルト値は application/x-www-form-urlencode です。これですと、フォームに入力した文字しか送信されません。 ファイルをアップロードする場合は、enctype属性値を "multipart/form-data" にしないといけません。 作成したフォームはそうなっていますか。そうでないと添付ファイルのデータは送信されません。

BullRider
質問者

補足

お返事ありがとうございます。 フォームを修正して(enctype="multipart/form-data")送信すると「HTTPエラー500」が発生しました。 これってCGIの問題ですかね。。やはりCGIを探すしか無いのでしょうか?