メール受信プログラムを作成しています。
ソケットの初期化・生成
↓
POP3サーバー接続
↓
アカウント送信
↓
パスワード送信
・・・までは上手くいくのですが、STATコマンドでメールの状態を取得しようとすると、
-ERRが返ってきてしまいます。
STATコマンドを送るときに、何か注意することがあるのでしょうか?
何かお気づきの方、いらっしゃいましたら、ご教授して頂けると幸いです。
どうぞよろしくお願い致します。
以下、STATコマンド送信のコードです。
//STATコマンドの送信
sprintf(szBuffer, "STAT\r\n");
send(Sock, szBuffer, strlen(szBuffer), 0);
char szReBuff[MAX_BUFF];
memset(szReBuff, 0, sizeof(szReBuff));
int nRe = recv(Sock, szReBuff, sizeof(szReBuff), 0);
if (nRe == SOCKET_ERROR || strncmp(szReBuff, "+OK", 3)){
closesocket(Sock);
WSACleanup();
return (FALSE);
}
> パスワード送信
> ・・・までは上手くいくのですが、STATコマンドでメールの状態を取得しようとすると、
> -ERRが返ってきてしまいます。
ちゃんと認証通っていますか?
> int nRe = recv(Sock, szReBuff, sizeof(szReBuff), 0);
> if (nRe == SOCKET_ERROR || strncmp(szReBuff, "+OK", 3)){
recvで2バイトしか取れていなかったら失敗しますが、そのヘンは大丈夫ですか?
ブレークポイント設定して、szReBuff[]に何が入っているか、
nReはいくつになっているか確認してみてはどうでしょう?
お答えありがとうございます。
パスワードまでの認証は通っております。
きちんと「+OK」が返ってきました。
STATコマンドに対するrecvの返り値は、「-ERR・・・・・・」状態です。
どうしてもここでエラーが返ってきてしまいます。
コードの書き方は、アカウントやパスワードのときと同じなのですが。
前回、環境を書き忘れておりました。申し訳ありません。
VC.Net 2003です。
開発はWindows XPで行っております。
引き続き、助言をお待ちしております。
どうぞよろしくお願い致します。
手っ取り早く、パケットをキャプチャしてみては?
キャプチャツールは色々ありますが
FreePeekとか
http://www.vector.co.jp/soft/winnt/net/se125800.html
ソケット通信のプログラムを作るときはあると便利です。
#telnetで正しくやり取りできるのは確認済みですか?
-ERRの後に何らかのメッセージは書いていないのですか?
編集 削除返信が遅くなりました。
お答え下さっていた、へむさん、YuOさん、申し訳ありません。
キャプチャツールは使ったことがありませんでした。
使ってみます。
「#telnet」は存在自体知りませんでした。
勉強不足ですね。調べてみようと思います。
「-ERR」のあとのメッセージなのですが、調べてみると
「-ERR Not yet authenticated」認証されていないとのメッセージでした。
何回か試しているうちに、時にエラーなく通ることもあるようです。
ご親切にお答え下さって、本当にありがとうございます。
ネットワークプログラムは学び始めたばかりで、至らない点ばかり
だと思いますが、もう少しお付き合い下さると幸いです。
同じようなネタのプログラムを作っているようなので・・・。
TelnetはTeraTerm等のソフトの総称と考えてかまわないです。
Windowsにも標準でTelnetが付いているので、それを使って
試してみると良いと思います。
起動方法は[スタート]-[すべてのプログラム]-[アクセサリ]-[コマンドプロンプト]で
コマンドプロンプトを出して以下のコマンドを入れて実行します。
C:\>telnet POPサーバ名(またはアドレス) ポート番号(標準なら110)
例としてpop.yourdomain.comだとしたら以下の通りです。
C:\>telnet pop.yourdomain.com 110
実行するとPOPサーバに接続されるので、以下のように入力します。
USER ユーザ名[ENTER]
PASS パスワード[ENTER]
例でユーザ名がmikenyan、パスワードがpassだとすると以下の通りです。
USER mikenyan[ENTER]
PASS pass[ENTER]
認証が正しければこのあとに現在届いているメールの数とメールの総バイト数が出ます。
ホストによってはSTATをたたかないと見れない場合もあります。
+OK xxx xxxx
例でMac OSXでTelnetした結果を載せておきます。(ホスト、ユーザ名、パスは架空です)
Clover-Server:〜 user1$ telnet pop.yourdomain.com 110
Trying XXX.XXX.XXX.XXX...
Connected to pop.yourdomain.com.
Escape character is '^]'.
+OK pop.yourdomain.com <33838122.1174567749@XXX.XXX.XXX.XXX.XXXXX>
USER mikenyan
+OK password please
PASS pass
+OK Maildrop locked and ready
LIST
+OK scan listing follows
1 24530
2 24680
.
STAT
+OK 2 49210
quit
+OK
Connection closed by foreign host
あとは奥の手なのですけれど、私の作っているプログラムのように
nMail.dllやBASP21.dllを使ってメールの件数を取得するのも手かもしれません。
> 「-ERR Not yet authenticated」認証されていないとのメッセージでした。
> 何回か試しているうちに、時にエラーなく通ることもあるようです。
あまり考えられませんが…
PASS送ってから、STAT送るまでが短いとか。
サーバ側の処理が遅れているとかでしょうかね。
PASS送出後のレスポンスで"+OK"を確認してから送っているんですよね?
100msほどSleepしてみるとかはどうでしょう?
telnetに関してはみけにゃんさんが書かれているので…
「telnet POP3」でググると参考になるページが見つかるんじゃないでしょうか。
あと、RFCも一応見ておいた方がいいかもしれません。
# spamなんかはよくRFCに従わないカタチで送ってくれやがりますが。
# 最近はGOOD MailerのDateヘッダに泣かされてます。(バッファオーバーランかましてしまいました)
ご丁寧な対応をありがとうございます。
みけにゃんさんの教えてくださった通りに、Telnetで確認を行いました。
問題なく受信状況を取得できるようです。
Sleepで待ってもみたのですが、改善されません。
いま作成しているのはWindowプログラムです。
試しにコンソールプログラムで作成してみたところ、何故か受信できるようになりました。
処理は特に変更していないのですが・・・
(ホスト・アカウントなどの情報取得方法がかわった程度です。
取得内容も同じであることを確認しました)
何か考えられる原因はありますでしょうか?
引き続き、どうぞよろしくお願い致します。
>Trying XXX.XXX.XXX.XXX...
>Connected to pop.yourdomain.com.
>Escape character is '^]'.
>+OK pop.yourdomain.com <33838122.1174567749@XXX.XXX.XXX.XXX.XXXXX>
サーバーからの応答でこの辺の部分の処理がうまくできていないとかは
ありませんか?
USERの前に「+OK」を送信してくるので「+OK」をひとつずれて取得しているとか・・
#予想で書いているので多分ハズレです。
全ての箇所のsendとrecvの下にTRACEを入れて
送信文字と受信文字を処理順に表示させてみるとどうなりますか?
とりあえず参考になるか分からないですけれど
Windowプログラム(SDK)であれば、猫でも分かるプログラミングの
SDK編3章にPOP3につないでメールの件名、差出人、受信日時
メールサイズをリストビューに一覧表示するプログラムが載っています。
http://www.kumei.jp/c_lang/sdk3/sdk_238.htm
>全ての箇所のsendとrecvの下にTRACEを入れて
WindowプログラムならMessageBox(NULL,デバッグ文字列変数,"DEBUG", MB_OK);を入れて
デバッグしてもよさそうな気がします・・・・。
> >全ての箇所のsendとrecvの下にTRACEを入れて
> WindowプログラムならMessageBox(NULL,デバッグ文字列変数,"DEBUG", MB_OK);を入れて
> デバッグしてもよさそうな気がします・・・・。
MessageBox()で処理が止まってしまうので、場合によっては不向きです。
(何十回とループする中に入れた場合とか)
他に、WM_PAINT関係やWM_ACTIVATE等に反応するモノの場合は
ほぼ無限ループに陥ってしまいます。
ということで、ログファイルに書き出すか、TRACE(SDKの場合はOutputDebugString)を使った方が便利なこともあります。
さて、本題ですが…
Sleep()でもダメだったようで。
ヘムさんの指摘のように実際のサーバとりやりとりを確認するのがまずは行うべきコトかと。
あと…認証通った後、QUITコマンドでちゃんとログアウトしていますか?
POP3の場合、たいていのサーバで多重ログインはできません。
認証後、QUITコマンドで抜ける必要があります。
(とはいえ、マトモなサーバならTCP接続が切れた時点でログアウト扱いしてくれるハズですが)
# クセのあるサーバもあったりするので注意が必要ですが。
# 私の使っているISPのサーバだと、LISTコマンドで取得したサイズと、
# メールのサイズが微妙に食い違うコトがあります。
## Statusヘッダの内容の増分でしたが。
>他に、WM_PAINT関係やWM_ACTIVATE等に反応するモノの場合は
>ほぼ無限ループに陥ってしまいます。
そこを考慮してなかったですね(>_<)
確認するものが単純にループしないものと想定して書いたんです。
さすがにWM_TIMER、WM_PAINT、WM_ACTIVATE等の
反応するものはログ出力(LogWrite()とかを自作して使う)した方が
良いのかもしれませんね。
>みけにゃん
すみません。確認方法を書いただけですので
MessageBoxでも勿論確認はできると思います。
問題解決の方法が複数あったほうが質問したかたの
助けになると思います。
私も本題です。
未解決でしたら受信部分の(できれば検証(再現)できる)
ソース部分を載せてみてはいかがでしょう。
#もうそれしかなさそうな
そういえば・・・メール受信プログラムとありますけれど
メールチェッカーか私のようなメールデータを受信して
ファイルにしてどこか指定したディレクトリに格納して
一覧にするような普通のメールソフトを作ろうとして
いるのでしょうか?
へむさんの言うようにソースを一部出した方が早期
解決につながるかもしれませんよ。
皆さん、本当にご親切に解答して下さって、ありがとうございます。
返信が遅れてしまって、申し訳ありませんでした。
解決致しました。
へむさんのおっしゃる通り、「connect」のあとの送信取得が
通っておりませんでした。
その部分を修正すると、エラーなく処理が走るようになりました。
初歩的なミスで、皆さんを煩わせて申し訳ありません。
一緒に考えてくださったこと、うれしく思います。
また何かありましたら、相談させて頂こうと思いますので、
そのときはあきれず、ご相手して下されば幸いです。
瀬戸っぷさん、へむさん、YuOさん、みけにゃんさん、
本当にありがとうございました。