PHPはソケットでメールを送る
25480 ワード
学習背景:
実際の仕事でメールの需要に遭遇した.既存のコードは、JSPページにアクセスしてjavaのメールクラスを呼び出すことで実現されます.最初はPHPの類も試したことがあるそうですが、時間がかかって問題になったようなので、そのまま「曲線救国」を始めました.既存の方法で自分の仕事を終えた後、なぜPHPを直接使うのが失敗したのか知りたいと思っています.PHPで直接機能を果たすことが望ましいので、効率的にはもっと高いはずです.
学習の経過:
1、既存のPHPメール類を探す2、PHPのmail()関数を使うが、ログインできないのでイントラネットメールしか送信できない.3、socket学習4、SMTPプロトコルコマンド学習5、cmdを利用してtelnet接続サーバーを通じて、SMTPコマンドメール6、socketを利用して、SMTPコマンドメール7、まとめデータ部分の符号化問題及びメールの添付ファイルフォーマット(1)タイトル符号化(2)本文分割(3)添付ファイルの具体的な本文(4)具体的な実現8、まとめ9、添付ファイル
注意:以下は3つのメールボックスサーバーを使用しました:1、会社の古いサーバー:mail.old.net 2、会社の新しいサーバー:mail.new.net 3、QQメールボックス:smtp.qq.com
1、既存のPHPメール類を探す:
コードの中の元のPHP類を見つけて、またネット上でいくつか他の人が書いたPHP類を探しました...コードが少なければ数百余りで千行以上...私の現在のレベルでその中の原理をかじってから問題点を見つけるのは難しいはずです...PEARをインストールしてからメールで広げる方法も見ましたが、なぜか私はインストールがずっと失敗していて、先に放棄するしかありません.
2、PHPのmail()関数を使いますが、ログインできないのでイントラネットメールしか送信できません:
PHP自体を思い出すとmail()関数があるのですが...だから...どうして誰も使っていないのですか?まずやってみよう...
具体的な実装:
1、php.iniの構成を変更する:
2、phpコード:mail($to,$subject,$message,$headers,$parameters)mail(受信者、タイトル、内容、メール原文に表示されるいくつかのパラメータは、よく使われていません)
説明:
1、メールの送信者と受信者:ini構成-->メール原文Return-Path$toパラメータ-->実際の受信者(イントラネットでなければならない)$headerパラメータ-->送信者を表示(任意に追加可能)$headerパラメータ-->受信者を表示(任意に記入可能)2、送信範囲:受信者はイントラネットでなければならない人:テスト状況:同じサーバー範囲のメールボックスのみ送信可能(@後の一致).外部ネットワークを送信する場合(会社のメールボックスがQQメールボックスを送信するなど)あ、エラーコードは554と550があります.推測:1、メールサーバーの設定の問題.2、mailからメールを送るには具体的なアカウントとパスワードを登録する必要がないので、外網を送信できません.注意:インタフェースに表示されている内容はtoの設定で他の人として表示できます.つまり:$to内網メールボックスを設定し、このメールボックスは実際にこのメールを受信します.しかし、このメールに表示されている受信者はこのイントラネットメールボックスではなく、$headersによって設定されています.3、符号化:コンテンツについてはbase 64で符号化してからUTF-8にします.形は:=?UTF-8?B?".base 64_encode("メールタイトル")."?=4、本文はHTMLコードを使います:$headersにContent-type:text/htmlを設定すればいいです
まとめ:
内部ネットワークのみでメールを行う場合は、mail()で十分ですが、外部ネットワークに連絡する必要がある場合は、mail()の解決策は見つかりません.
3、ソケット学習
ネット上で探しているクラスの中に、コード量が少ないものが見つかりました.socketメソッドを使用しています.まずsocketを勉強して、このクラスを理解してみてください.
socketの大まかな意味:
socketサーバ:ポートを開き、リスニングを継続し、情報を受信し、情報を返信します.socketクライアント:特定のポートに情報を送信し、サーバの返信を受け入れる情報.
具体的な実装:
サーバコード:
クライアントコード:
説明:
ブラウザアクセスのみをテストし、cmdでは実行しませんでした.(ブラウザアクセス:先サーバ、後クライアント)現在、クライアントが最初にアクセスした後にサーバが停止しており、2回目のアクセス時にエラーが表示されます.socket_close()コメントが落ちます&&socket_listen()2番目のパラメータ>1は、依然として無効です.サーバをリスニングし続ける方法が分かりません.
まとめ:
SOcketの意味と簡単な使用が初歩的に分かった.より多くのパラメータや方法の使用などについて後で深く勉強する.
4、SMTPプロトコル命令学習
SMTP常用コマンド(大文字と小文字は関係ありません):
各コマンドはステータスコード+簡単な説明を返し、成功に失敗したことを通知します.
5、cmdを利用してtelnetを通じてサーバーに接続し、SMTPコマンドを送ってメールを送る
telnet使用:
サーバーに接続した後に具体的なコマンドを入力します.この場合、チェックアウトキーは使用できません.
古いサーバ:mail.old.net
auth loginログインできません
会社の新しいサーバー:mail.new.net
ログインするかどうかにかかわらず、メールを送ることができます.1、auth loginはログインしません
2、auth loginログインポートが25であろうと587であろうと、starttls後にアカウント登録ができない.また、mail fromおよびrcpt toがQQメールボックスに記入されている場合、QQメールボックスは無効であることが分かった.
QQメールボックスサーバー:smtp.qq.com 587
QQメールボックスに設定し、P 0 P 3/SMTPをオンにする必要があります.QQメールボックスはstarttlsをオンにしてからログインし、外部ネットワークにメールを送信することができます.
説明:
1、送信範囲:会社の古いメールアドレス:イントラネットしかできない.会社の新しいメールアドレス:イントラネットを登録しないで、イントラネットしかできない.QQメールアドレス:先にstarttlsを登録してから、イントラネットができる.2、具体的な送信者の受信者:登録したアカウント-->実際の送信者mail from-->原文Return-Pathの内容rcpt to-->実際の受信者data-from-->表示される送信者(任意に記入可能)data-to-->表示される受信者(任意に記入可能、実際とは異なる)3、その他:符号化および添付ファイル未テスト
まとめ:
mail()と同様に、ログインしない場合は、イントラネットでしか送信できませんが、telnetではauth loginでアカウントにログインし、外部ネットにメールを送信することができます.
6、SOcketを利用して、SMTPコマンドを送信してメールを送る
SOcketの送信の概要:
説明:
1、SMTPコマンドを複数回socket_write()で送信し、メール全体の流れを完了する2、rはコマンドラインでリターン3、QQメールボックスで使用できないことに等しい:auth loginコマンド後:エラー表示:unable to read from socket[0]:リモートホストが既存の接続を強制的に閉じた.安全性の考慮にあるかもしれない??
7、data部分の符号化問題及びメールの添付ファイルフォーマットをまとめる
资料を调べて符号化と本文のフォーマットを探して、しかし大部分は比较的に乱れて、さもなくばRFCファイルは勇気がありません.后で自分で自分にメールを送ることを思い付いて、それからメールの原文を见るこの机能を使って、自分で総括します.
(1)タイトルコード:
(2)本文分割:
宣言が必要です:Content-Type:multipart/mixed.mixedはブレンドタイプを示します.boundary分割を規定し、具体的な宣言+内容を具体的な状況に応じてそれぞれ書きます.
boundary分割ルール:
boundaryはカスタムの最初のセグメントの開始です.--boundaryのn番目のセグメントの開始:--boundaryの終了:--boundary--boundaryはネストできます.テキストと添付ファイルの場合、一般的にネストする必要はありません.
全体は次のようになります.
(3)添付書類の具体的な本文
宣言と内容、内容と後文はすべて空行が必要で、つまり2回r
html:
添付ファイル:
まずfopen()およびfread()でバイナリを読み出し,バイナリコンテンツを送信する
次に、エンコーディング・タイプを宣言し、データを渡します.
説明:
1、ファイル名の符号化:ファイル名の符号化は2回あり、1回はファイルを開くため、1回はメールの表示のためである.符号化方式が異なり、統一できるかどうか分からない.2、開始の声明の中で、boundaryの前にTabキーのインデントが必要である:原因不明
3、添付ファイルの声明:他人のコードを見て、ファイルの接尾辞で判断するタイプのようです.自分はアプリケーション/octet-streamを大まかに使うだけです.
(4)具体的な実現:
send_email.phpファイル添付ファイル1
自分でまとめたメール送信関数の欠陥は、追加されていません:1、コピー者、密輸者がいません.2、コマンド送信が成功したかどうかを判断していません(正則でリターンコードを判断できます).3、textかhtmlかを選択していないので、すべてデフォルトでhtmlになっています.4、starttlsかどうかを選択していません.QQメールボックスに使用する必要がある場合は、自分で追加する必要があります.5、変数名とコードフォーマットはあまり規範的ではないかもしれません.
Email.phpファイル添付ファイル2
ネット上にカプセル化されたクラスは、socketでメールを送信します.
8、まとめ:
上記の内容は三日間ぐらい勉強とテストをして、それから整理するのに一日以上かかりました.以前はsocketが深くて計り知れないと思っていましたが、今は少なくともある程度の理解があって、そんなに怖くありません.QQメールボックスは登録しなければなりません.そしてmail fromの送信者は登録者でなければなりません.誰かがわざと自分の本当の住所を隠すのを防ぐことができます.だから、会社の新しいメールボックスは登録しなくてもいいです.陸の場合、セキュリティホールに属していると推定されますか?PHPコードの知識を再熟知した後、その数千行のPHP類を研究しなければなりません...具体的な実現原理はいったいどうなっているのか分かりません...
9、添付資料:
添付ファイル一:send_email.php
添付ファイル2:email.php
実際の仕事でメールの需要に遭遇した.既存のコードは、JSPページにアクセスしてjavaのメールクラスを呼び出すことで実現されます.最初はPHPの類も試したことがあるそうですが、時間がかかって問題になったようなので、そのまま「曲線救国」を始めました.既存の方法で自分の仕事を終えた後、なぜPHPを直接使うのが失敗したのか知りたいと思っています.PHPで直接機能を果たすことが望ましいので、効率的にはもっと高いはずです.
学習の経過:
1、既存のPHPメール類を探す2、PHPのmail()関数を使うが、ログインできないのでイントラネットメールしか送信できない.3、socket学習4、SMTPプロトコルコマンド学習5、cmdを利用してtelnet接続サーバーを通じて、SMTPコマンドメール6、socketを利用して、SMTPコマンドメール7、まとめデータ部分の符号化問題及びメールの添付ファイルフォーマット(1)タイトル符号化(2)本文分割(3)添付ファイルの具体的な本文(4)具体的な実現8、まとめ9、添付ファイル
注意:以下は3つのメールボックスサーバーを使用しました:1、会社の古いサーバー:mail.old.net 2、会社の新しいサーバー:mail.new.net 3、QQメールボックス:smtp.qq.com
1、既存のPHPメール類を探す:
コードの中の元のPHP類を見つけて、またネット上でいくつか他の人が書いたPHP類を探しました...コードが少なければ数百余りで千行以上...私の現在のレベルでその中の原理をかじってから問題点を見つけるのは難しいはずです...PEARをインストールしてからメールで広げる方法も見ましたが、なぜか私はインストールがずっと失敗していて、先に放棄するしかありません.
2、PHPのmail()関数を使いますが、ログインできないのでイントラネットメールしか送信できません:
PHP自体を思い出すとmail()関数があるのですが...だから...どうして誰も使っていないのですか?まずやってみよう...
具体的な実装:
1、php.iniの構成を変更する:
SMTP = mail.old.net //
smtp_port = 25 // , 25
sendmail_from = "[email protected]" // (win )
;sendmail_path = "" //unix ?
2、phpコード:mail($to,$subject,$message,$headers,$parameters)mail(受信者、タイトル、内容、メール原文に表示されるいくつかのパラメータは、よく使われていません)
$to = "[email protected]";
$subject = "=?UTF-8?B?".base64_encode(" ")."?=";
$message = "クリックして ジャンプできます";
$headers = << \r
to:" \r
HEADERS;
$boolean = mail($to, $subject, $message, $headers); //
説明:
1、メールの送信者と受信者:ini構成-->メール原文Return-Path$toパラメータ-->実際の受信者(イントラネットでなければならない)$headerパラメータ-->送信者を表示(任意に追加可能)$headerパラメータ-->受信者を表示(任意に記入可能)2、送信範囲:受信者はイントラネットでなければならない人:テスト状況:同じサーバー範囲のメールボックスのみ送信可能(@後の一致).外部ネットワークを送信する場合(会社のメールボックスがQQメールボックスを送信するなど)あ、エラーコードは554と550があります.推測:1、メールサーバーの設定の問題.2、mailからメールを送るには具体的なアカウントとパスワードを登録する必要がないので、外網を送信できません.注意:インタフェースに表示されている内容はtoの設定で他の人として表示できます.つまり:$to内網メールボックスを設定し、このメールボックスは実際にこのメールを受信します.しかし、このメールに表示されている受信者はこのイントラネットメールボックスではなく、$headersによって設定されています.3、符号化:コンテンツについてはbase 64で符号化してからUTF-8にします.形は:=?UTF-8?B?".base 64_encode("メールタイトル")."?=4、本文はHTMLコードを使います:$headersにContent-type:text/htmlを設定すればいいです
まとめ:
内部ネットワークのみでメールを行う場合は、mail()で十分ですが、外部ネットワークに連絡する必要がある場合は、mail()の解決策は見つかりません.
3、ソケット学習
ネット上で探しているクラスの中に、コード量が少ないものが見つかりました.socketメソッドを使用しています.まずsocketを勉強して、このクラスを理解してみてください.
socketの大まかな意味:
socketサーバ:ポートを開き、リスニングを継続し、情報を受信し、情報を返信します.socketクライアント:特定のポートに情報を送信し、サーバの返信を受け入れる情報.
具体的な実装:
サーバコード:
set_time_limit(0); // ,cmd
$socket = socket_create(AF_INET, SOCK_STREAM, 0); // socket
socket_bind($socket, "127.0.0.1", 16161); // socket
socket_listen($socket, 3); // , ( ?)?
$receive_socket = socket_accept($socket); // , socket
$input = socket_read($receive_socket, 1024); // socket
var_dump($input); // , ?
$output = " --> ";
socket_write($receive_socket, $output, strlen ($output)); // 。 : socket , 。
socket_close($socket); //
socket_close($receive_socket);
クライアントコード:
$socket = socket_create(AF_INET, SOCK_STREAM, 0); // socket
socket_connect($socket, "127.0.0.1", 16161); //
$message = " --> ";
socket_write($socket, $message, strlen($message)); //
$result = socket_read ($socket, 1024); //
var_dump($resule);
socket_close($socket); // socket
説明:
ブラウザアクセスのみをテストし、cmdでは実行しませんでした.(ブラウザアクセス:先サーバ、後クライアント)現在、クライアントが最初にアクセスした後にサーバが停止しており、2回目のアクセス時にエラーが表示されます.socket_close()コメントが落ちます&&socket_listen()2番目のパラメータ>1は、依然として無効です.サーバをリスニングし続ける方法が分かりません.
まとめ:
SOcketの意味と簡単な使用が初歩的に分かった.より多くのパラメータや方法の使用などについて後で深く勉強する.
4、SMTPプロトコル命令学習
SMTP常用コマンド(大文字と小文字は関係ありません):
各コマンドはステータスコード+簡単な説明を返し、成功に失敗したことを通知します.
// ,220
helo xxx // !xxx ,250
ehlo xxx //xxx , , 250-xxx 250-xxx
starttls //QQ
auth login // , base64 ,
mail from: // ,250
rept to:// 、 、250に り し
data// なメール 、 されるfrom-to、 および ファイルはすべてここで され、 で (r.r)、354+250
quit// を 、221
5、cmdを利用してtelnetを通じてサーバーに接続し、SMTPコマンドを送ってメールを送る
telnet使用:
サーバーに接続した後に具体的なコマンドを入力します.この場合、チェックアウトキーは使用できません.
telnet host port // 25 QQ 587(SSL , 465 587, 465 )
古いサーバ:mail.old.net
auth loginログインできません
telnet mail.old.net 25 //220
helo abc //250
ehlo abc // 250-xx 250-xx
mail from: // Return-Path, ,250
rcpt to: // ( ),250
data //354
from: random@random // ( )
to: random@random // ( )
comment-comment //
. // . ,250
quit //221
会社の新しいサーバー:mail.new.net
ログインするかどうかにかかわらず、メールを送ることができます.1、auth loginはログインしません
telnet mail.new.net 25 //220
helo abc //250
ehlo abc // 250-xx 250-xx
mail from: // Return-Path, ,250
rcpt to: // ( ),250
data //354
from:random@random // ( )
to: random@random // ( )
comment-comment //
. // . ,250
quit //221
2、auth loginログインポートが25であろうと587であろうと、starttls後にアカウント登録ができない.また、mail fromおよびrcpt toがQQメールボックスに記入されている場合、QQメールボックスは無効であることが分かった.
telnet mail.new.net 25 //220
helo abc //250
ehlo abc // 250-xx 250-xx
auth login //334
base64abcdefg //@ base64 ,334
base64abcdefg // base64 ,235
mail from: // Return-Path, ,250
rcpt to: // , ,250
data //354
from:random@random // ( )
to: random@random // ( )
comment-comment //
. // . ,250
quit //221
QQメールボックスサーバー:smtp.qq.com 587
QQメールボックスに設定し、P 0 P 3/SMTPをオンにする必要があります.QQメールボックスはstarttlsをオンにしてからログインし、外部ネットワークにメールを送信することができます.
telnet smtp.qq.com 587 //220
helo abc //250
ehlo abc // 250-xx 250-xx
starttls //220
auth login //334
base64abcdefg //@ base64 ,334
base64abcdefg // base64 ,235
mail from: // Return-Path, ,250
rcpt to: // , ,250
data //354
from:random@random // ,
to: random@random // ,
comment-comment //
. // . ,250
quit //221
説明:
1、送信範囲:会社の古いメールアドレス:イントラネットしかできない.会社の新しいメールアドレス:イントラネットを登録しないで、イントラネットしかできない.QQメールアドレス:先にstarttlsを登録してから、イントラネットができる.2、具体的な送信者の受信者:登録したアカウント-->実際の送信者mail from-->原文Return-Pathの内容rcpt to-->実際の受信者data-from-->表示される送信者(任意に記入可能)data-to-->表示される受信者(任意に記入可能、実際とは異なる)3、その他:符号化および添付ファイル未テスト
まとめ:
mail()と同様に、ログインしない場合は、イントラネットでしか送信できませんが、telnetではauth loginでアカウントにログインし、外部ネットにメールを送信することができます.
6、SOcketを利用して、SMTPコマンドを送信してメールを送る
SOcketの送信の概要:
$socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); // socket
socket_connect($socket, $mail_server_name, $mail_server_port); //
$command = "helo abc \r
"; // \r
socket_write($socket, $command, strlen($command)); //
$num = socket_read($socket, 1024); //
説明:
1、SMTPコマンドを複数回socket_write()で送信し、メール全体の流れを完了する2、rはコマンドラインでリターン3、QQメールボックスで使用できないことに等しい:auth loginコマンド後:エラー表示:unable to read from socket[0]:リモートホストが既存の接続を強制的に閉じた.安全性の考慮にあるかもしれない??
7、data部分の符号化問題及びメールの添付ファイルフォーマットをまとめる
资料を调べて符号化と本文のフォーマットを探して、しかし大部分は比较的に乱れて、さもなくばRFCファイルは勇気がありません.后で自分で自分にメールを送ることを思い付いて、それからメールの原文を见るこの机能を使って、自分で総括します.
(1)タイトルコード:
$subject = "=?UTF-8?B?".base64_encode(" ")."?=";
(2)本文分割:
宣言が必要です:Content-Type:multipart/mixed.mixedはブレンドタイプを示します.boundary分割を規定し、具体的な宣言+内容を具体的な状況に応じてそれぞれ書きます.
boundary分割ルール:
boundaryはカスタムの最初のセグメントの開始です.--boundaryのn番目のセグメントの開始:--boundaryの終了:--boundary--boundaryはネストできます.テキストと添付ファイルの場合、一般的にネストする必要はありません.
全体は次のようになります.
- -boundary
--boundary
-
--boundary
-
--boundary
-
--boundary--
(3)添付書類の具体的な本文
宣言と内容、内容と後文はすべて空行が必要で、つまり2回r
html:
$command = <<
添付ファイル:
まずfopen()およびfread()でバイナリを読み出し,バイナリコンテンツを送信する
$file_name = iconv('UTF-8', 'GB18030', " .txt" ); //
$fp = fopen($file_name, 'rb'); //
$comment = fread($fp, filesize($file_name)); //
fclose($fp); //
次に、エンコーディング・タイプを宣言し、データを渡します.
$file_name = "=?UTF-8?B?".base64_encode(" .txt")."?="; //
$command = "Content-Type: application/octet-stream; \r
"
$command .= "name=\"" . $file_name . "\"\r
"
$command .= "Content-Disposition: attachment; filename=\"" . $file_name . "\"\r
";
$command .= "Content-Transfer-Encoding: base64 \r
";
$command .= "\r
" . base64_encode($comment) . "\r
\r
"; // $comment
説明:
1、ファイル名の符号化:ファイル名の符号化は2回あり、1回はファイルを開くため、1回はメールの表示のためである.符号化方式が異なり、統一できるかどうか分からない.2、開始の声明の中で、boundaryの前にTabキーのインデントが必要である:原因不明
"Mime-Version: 1.0\r
Content-Type: multipart/mixed;\r
boundary=\"".$boundary."\"\r
Content-Transfer-Encoding: 8Bit\r
";
3、添付ファイルの声明:他人のコードを見て、ファイルの接尾辞で判断するタイプのようです.自分はアプリケーション/octet-streamを大まかに使うだけです.
(4)具体的な実現:
send_email.phpファイル添付ファイル1
自分でまとめたメール送信関数の欠陥は、追加されていません:1、コピー者、密輸者がいません.2、コマンド送信が成功したかどうかを判断していません(正則でリターンコードを判断できます).3、textかhtmlかを選択していないので、すべてデフォルトでhtmlになっています.4、starttlsかどうかを選択していません.QQメールボックスに使用する必要がある場合は、自分で追加する必要があります.5、変数名とコードフォーマットはあまり規範的ではないかもしれません.
Email.phpファイル添付ファイル2
ネット上にカプセル化されたクラスは、socketでメールを送信します.
8、まとめ:
上記の内容は三日間ぐらい勉強とテストをして、それから整理するのに一日以上かかりました.以前はsocketが深くて計り知れないと思っていましたが、今は少なくともある程度の理解があって、そんなに怖くありません.QQメールボックスは登録しなければなりません.そしてmail fromの送信者は登録者でなければなりません.誰かがわざと自分の本当の住所を隠すのを防ぐことができます.だから、会社の新しいメールボックスは登録しなくてもいいです.陸の場合、セキュリティホールに属していると推定されますか?PHPコードの知識を再熟知した後、その数千行のPHP類を研究しなければなりません...具体的な実現原理はいったいどうなっているのか分かりません...
9、添付資料:
添付ファイル一:send_email.php
";
$file_name[0] = " .png";
$file_name[1] = " .xlsx";
$file_name[2] = " .docx";
$file_name[3] = " .pdf";
send_email($mail_server_name, $username, $passward, $mail_from, $mail_to, $html_comment, $file_name, $subject);
/**
* socket
* @param $mail_server_name
* @param $username
* @param $passward
* @param $mail_from
* @param $mail_to ,
* @param $html_comment
* @param array $file_name ,
* @param string $subject ,
* @param string $mail_server_port 25
* @param string $boundary
*/
function send_email($mail_server_name, $username, $passward, $mail_from, $mail_to, $html_comment, $file_name=array(), $subject="", $mail_server_port="25", $boundary="ABCDEFG"){
// socket
$socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
// , 220
socket_connect($socket, $mail_server_name, $mail_server_port);
//helo localhost, 250
$command = "helo localhost\r
";
socket_write($socket, $command, strlen($command));
socket_read($socket, 1024);
// , 334 334 235
$command = "auth login\r
";
socket_write($socket, $command, strlen($command));
socket_read($socket, 1024);
// 334
$command = base64_encode($username)."\r
";
socket_write($socket, $command, strlen($command));
socket_read($socket, 1024);
// 235
$command = base64_encode($passward)."\r
";
socket_write($socket, $command, strlen($command));
socket_read($socket, 1024);
// , 250
$command = "MAIL FROM:\r
";
socket_write($socket, $command, strlen($command));
socket_read($socket, 1024);
// , 250
$mail_to_length = count($mail_to);
for($i=0; $i\r
";
socket_write($socket, $command, strlen($command));
socket_read($socket, 1024);
}
// , 354
$command = "DATA\r
";
socket_write($socket, $command, strlen($command));
socket_read($socket, 1024);
// : 250
$command = "from: ".$mail_from."\r
";
for($i=0; $i
添付ファイル2:email.php
");
define("EOL", "\r
");
define("SMTP_HOST", "mail.new.net"); //SMTP
define("SMTP_PORT", "25"); //SMTP
define("SMTP_USER", ""); //SMTP
define("SMTP_PASS", ""); //SMTP
$from = "random@random"; //SMTP
$to = "random@random"; //
$cc = "";
$bcc = "";
$subject=" ";
$subject=iconv("utf-8","gb2312//IGNORE",$subject); // ,
$body = " "; //
$smtp = new smtp(SMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASS, false); // true , .
$smtp-?>addAttachment("123.doc"," .doc");
$smtp->sendmail($to, $from, $subject, $body, $cc, $bcc);
class smtp {
/* Public Variables */
public $attachments = array();
/* Private Variables */
private $smtp_host;
private $smtp_port;
private $time_out;
private $host_name;
private $auth;
private $user;
private $pass;
private $sock;
/* Constractor */
public function smtp($smtp_host = null, $smtp_port = null, $user = null, $pass = null, $auth = true) {
$this->smtp_host = (!empty($smtp_host)) ? $smtp_host : SMTP_HOST;
$this->smtp_port = (!empty($smtp_port)) ? $smtp_port : SMTP_PORT;
$this->user = (!empty($user)) ? $user : SMTP_PORT;
$this->pass = (!empty($pass)) ? $pass : SMTP_PORT;
$this->auth = $auth;
$this->time_out = 15;
#
$this->host_name = "localhost";
$this->sock = FALSE;
}
/* Main Function */
public function sendmail($to, $from, $subject = "", $body = "", $cc = "", $bcc = "") {
$bndp = md5(uniqid("")) . rand(1000, 9999);
$bnd = md5(uniqid("")) . rand(1000, 9999);
list ($msec, $sec) = explode(" ", microtime());
$mail_from = $this->strip_line_breaks($from);
$mail_to = explode(",", $to);
$body = preg_replace("/(^|(\r
))(\\.)/", "", $body);
if ($cc != "") $mail_to = array_merge($mail_to, explode(",", $cc));
if ($bcc != "") $mail_to = array_merge($mail_to, explode(",", $bcc));
$headers = "MIME-Version:1.0" . EOL;
$headers .= "To: " . $to . EOL;
if ($cc != "") {
$headers .= "Cc: " . $cc . EOL;
}
$headers .= "From: $from" . EOL;
$headers .= "Subject: " . $subject . EOL;
$headers .= "Date: " . date("r") . EOL;
$headers .= "X-Mailer: Webmail ver 1.0 (PHP Version/" . phpversion() . ")" . EOL;
$headers .= "Message-ID: " . EOL;
if (count($this->attachments) > 0) {
$headers .= "Content-Type: multipart/mixed;" . EOL . chr(9) . " boundary=\"" . $bndp . "\"" . EOL . EOL;
$headers .= '--'.$bndp . EOL;
$headers .= 'Content-Type : multipart/alternative; boundary="' . $bnd . '"' . EOL . EOL;
$headers .= '--' . $bnd . EOL;
$headers .= 'Content-Type: text/plain; charset=utf-8' . EOL;
$headers .= "Content-Transfer-Encoding: 8bit" . EOL . EOL;
$headers .= $body . EOL;
$headers .= '--' . $bnd . EOL;
$headers .= 'Content-type: text/html; charset=utf-8' . EOL;
$headers .= "Content-Transfer-Encoding: 8bit" . EOL . EOL;
$headers .= $body . EOL;
$headers .= '--' . $bnd . '--' . EOL;
foreach ($this->attachments as $att) {
$headers .= "--" . $bndp . EOL . $att;
print_R($headers);
}
$headers .= '--' . $bndp . '--' . EOL;
$this->clear_attachments();
} else {
$headers .= 'Content-Type : multipart/alternative;boundary="'.$bnd.'"' . EOL . EOL;
$headers .= '--'.$bnd . EOL;
$headers .= 'Content-Type: text/plain; charset=utf-8' . EOL;
$headers .= "Content-Transfer-Encoding: 8bit" . EOL . EOL;
$headers .= $body . EOL;
$headers .= '--'.$bnd . EOL;
$headers .= 'Content-type: text/html; charset=utf-8' . EOL;
$headers .= "Content-Transfer-Encoding: 8bit" . EOL . EOL;
$headers .= $body . EOL;
$headers .= '--'.$bnd.'--' . EOL;
}
$sent = TRUE;
foreach ($mail_to as $rcpt_to) {
$rcpt_to = $this->strip_line_breaks($rcpt_to);
if (!$this->smtp_sockopen($rcpt_to)) {
$this->log_write("Error: Cannot send email to " . $rcpt_to);
$sent = FALSE;
continue;
}
if ($this->smtp_send($this->host_name, $mail_from, $rcpt_to, $headers, $body)) {
$this->log_write("E-mail has been sent to ");
} else {
$this->log_write("Error: Cannot send email to ");
$sent = FALSE;
}
fclose($this->sock);
}
$this->log_write("{$mail_to} send over;");
return $sent;
}
public function addAttachment($file,$file_name="", $dispo = "attachment") {
$file_data = (file_exists($file)) ? file_get_contents($file) : "";
if ($file_data != "") {
$filename = basename($file);
if(!$file_name) $file_name=$filename;
$file_name="=?UTF-8?B?".base64_encode($file_name)."?=";
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$chunks = chunk_split(base64_encode($file_data));
$parts = "Content-Type: application/$ext; name=\"" . $file_name . "\"" . EOL;
$parts .= "Content-Transfer-Encoding: base64" . EOL;
$parts .= "Content-Disposition: " . $dispo . "; filename=\"" . $file_name . "\"" . EOL . EOL;
$parts .= $chunks . EOL . EOL;
$this->attachments[] = $parts;
}
}
private function clear_attachments() {
unset($this->attachments);
$this->attachments = array();
}
/* Private Functions */
private function smtp_send($helo, $from, $to, $header, $body = "") {
if (!$this->smtp_putcmd("HELO", $helo)) {
//$this->log_write("Error: Error occurred while sending HELO command.");
return FALSE;
}
#auth
if ($this->auth) {
if (!$this->smtp_putcmd("AUTH LOGIN", base64_encode($this->user))) {
//$this->log_write("Error: Error occurred while sending HELO command.");
return FALSE;
}
if (!$this->smtp_putcmd("", base64_encode($this->pass))) {
//$this->log_write("Error: Error occurred while sending HELO command.");
return FALSE;
}
}
if (!$this->smtp_putcmd("MAIL", "FROM:")) {
//$this->log_write("Error: Error occurred while sending MAIL FROM command.");
return FALSE;
}
if (!$this->smtp_putcmd("RCPT", "TO:")) {
//$this->log_write("Error: Error occurred while sending RCPT TO command.");
return FALSE;
}
if (!$this->smtp_putcmd("DATA")) {
//$this->log_write("Error: Error occurred while sending DATA command.");
return FALSE;
}
if (!$this->smtp_message($header, $body)) {
//$this->log_write("Error: Error occurred while sending message.");
return FALSE;
}
if (!$this->smtp_eom()) {
//$this->log_write("Error: Error occurred while sending . [EOM].");
return FALSE;
}
if (!$this->smtp_putcmd("QUIT")) {
//$this->log_write("Error: Error occurred while sending QUIT command.");
return FALSE;
}
return TRUE;
}
private function smtp_sockopen($address) {
if ($this->smtp_host == "") {
return $this->smtp_sockopen_mx($address);
} else {
return $this->smtp_sockopen_relay();
}
}
private function smtp_sockopen_relay() {
$this->log_write("Trying to Connect " . $this->smtp_host . ":" . $this->smtp_port . "...");
$this->sock = @fsockopen($this->smtp_host, $this->smtp_port, $errno, $errstr, $this->time_out);
if (!($this->sock && $this->smtp_ok())) {
$this->log_write("Error: connenct error" . $errstr . " (" . $errno . ")");
return FALSE;
}
$this->log_write("Connected Ok");
return TRUE;
}
private function smtp_sockopen_mx($address) {
$domain = preg_replace("/^.+@([^@]+)$/", "\1", $address);
if (!@getmxrr($domain, $MXHOSTS)) {
$this->log_write("Error: Cannot resolve MX \"" . $domain . "\"");
return FALSE;
}
foreach ($MXHOSTS as $host) {
$this->log_write("Trying to " . $host . ":" . $this->smtp_port);
$this->sock = @fsockopen($host, $this->smtp_port, $errno, $errstr, $this->time_out);
if (!($this->sock && $this->smtp_ok())) {
$this->log_write("Connect Error ," . $errstr . " (" . $errno . ")");
continue;
}
$this->log_write("Connected to mx host " . $host);
return TRUE;
}
$this->log_write("Error: Cannot connect to any mx hosts (" . implode(", ", $MXHOSTS) . ")");
return FALSE;
}
private function smtp_message($header, $body) {
fputs($this->sock, $header . "\r
" . $body);
return TRUE;
}
private function smtp_eom() {
fputs($this->sock, "\r
.\r
");
return $this->smtp_ok();
}
private function smtp_ok() {
$response = str_replace("\r
", "", fgets($this->sock, 512));
if (!preg_match("/^[23]/", $response)) {
fputs($this->sock, "QUIT\r
");
fgets($this->sock, 512);
$this->log_write("Error: Remote host returned \"" . $response . "\"");
return FALSE;
}
return TRUE;
}
private function smtp_putcmd($cmd, $arg = "") {
if ($arg != "") $cmd = ($cmd == "") ? $arg : ($cmd . " " . $arg);
fputs($this->sock, $cmd . "\r
");
return $this->smtp_ok();
}
private function strip_line_breaks($address) {
$address = preg_replace("/([\t\r
])+/", "", $address);
$address = preg_replace("/^.*.*$/", "", $address);
return $address;
}
public function log_write($message) {
$message = date("M d H:i:s ") . get_current_user() . "[" . getmypid() . "]: " . $message;
file_put_contents(dirname(__FILE__) . '/mail.log', $message . PHP_EOL, FILE_APPEND | LOCK_EX);
}
}