- - PR -
メール送信時のエラー処理方法
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-06-25 19:41
よろしくお願いします。
メール送信時のエラー処理方法で、いい方法を教えて頂けないでしょうか? 環境: WinXPPro、VS.NET2003、C# System.Web.Mail.SmtpMail.Sendメソッドでの送信でのエラーが発生した場合に 以下のようにキャッチして処理しています。 キャッチした例外によって再送処理を行うかのフラグを変更しています。 再送処理は、1時間ごとに行うようにします。 再送するかしないかの判断は、 再送したら送信されるかもしれない場合(メールサーバ落ちていた場合)は、 再送するようにしようと思っています。 下記だと、メルアドが設定されていない場合などは何回送信処理をしても送信には失敗するので再送なしと設定しています。
Console.WriteLine(e.InnerException); で出力してみると、 System.Reflection.TargetInvocationException: 呼び出しのターゲットが例外をスローしました。 ---> System.Runtime.InteropServices.COMException (0x80040213): 転送においてサーバーに接続できませんでした。 と出力されたので、COMExceptionのMessageがエラー原因として理解できるので、 そのMessageで比較するようにしているのですが・・・。 送信するメールサーバによってメッセージが変わったらお終いなんですが、 同じエラーでもメールサーバによって、返ってくるメッセージは変わるのでしょうか? 本当は、エラー番号等を取得して、再送フラグの設定処理を分けるといったことを したかったのですが、取得方法がわからなかったので、 上記のような処理になってしまいました>< 「再送なし」となるエラーを取得する方法として、 もっといい処理方法を教えていただけないでしょうか? catch(Exception e){ if( 再送なしになるようなエラーの場合 ){ 再送フラグ「なし」にセット } else{ 再送フラグ「あり」にセット } } という感じにしたいと思っています。 「再送なしになるようなエラー」は、 ・From,Toのメールアドレス未設定 ・521 指定した<ドメイン>がメールを受け付けない(認証に失敗?) ・550 メールボックスが利用不可能である。例:メールボックスが存在しない ・551 ユーザがローカルに存在しない ・552 ストレージの割りあてが上回った場合 ・553 メールボックス名は許可されない(例えばメールボックスの構文が正しくない) だと、いくら再送してもエラーになると考えてるのですが、 他には何が考えられるでしょうか? 長くなってすみません。 よろしくお願いします。m(_ _)m | ||||||||||||
|
投稿日時: 2004-06-28 08:52
少なくともこの例は、送信する前にわかるのではないでしょうか? COMException.ErrorCodeは、どうでした? | ||||||||||||
|
投稿日時: 2004-06-28 09:42
Jitta さん、返信ありがとうございます。
COMExceptionのエラーコードは気になってはいたのですが、 取得方法がわかりません。 using System.Runtime.InteropServices; catch(COMException ec) { Console.WriteLine("E-Code: "+ ec.ErrorCode); } catch(Exception e) { ・・・・ } としたのですが、COMExceptionをキャッチしてくれません。 InnerExceptionの取得はどのようにすればいいのでしょうか? よろしくお願いします。m(_ _)m | ||||||||||||
|
投稿日時: 2004-06-28 10:11
例外のスタックから、COMExceptionが発生していることがわかっているが、受けた例外は別のクラスである、ということですね? 未検証直打ち
一応、こんな風に潜っていくことはできます。 拾い出しは、
こんな感じ。 | ||||||||||||
|
投稿日時: 2004-06-28 11:55
Jitta さん、返信ありがとうございます。
do{ e = e.InnerException; if (e is COMException ) { COMException ce = (COMException) e; Console.WriteLine("E-Code: " + ce.ErrorCode); break; } }while( e!=null); とすれば、ErrorCodeを見れました。 InnerExceptionをCOMExceptionでキャストすればよかったんですね>< 気づきませんでした。 COMException.ErrorCode ですが、 SMTP通信エラー時の応答コードとは、関係ないんですね>< SMTP通信エラー時の応答コードは、(応答コードを取得したいなら) COMExceptionのMessage内から取得ということになるのでしょうか? よろしくお願いします。m(_ _)m | ||||||||||||
|
投稿日時: 2004-06-28 14:08
これだと一番外の例外が評価されないので、今回の例ではかまわないのですが、あまりよいコードではありません。 COMExceptionの発生元はありませんでしたか?(InnerExceptionはNULLでしたか?) | ||||||||||||
|
投稿日時: 2004-06-28 15:38
Jitta さん、返信ありがとうございます。
キャッチしたException( e )を、 Console.WriteLine( e.ToString() ); とすると、 System.Web.HttpException: 'CDO.Message' オブジェクトにアクセスできませんでした。 ---> System.Reflection.TargetInvocationException: 呼び出しのターゲットが例外をスローしました。 ---> System.Runtime.InteropServices.COMException (0x8004020E): サーバーによって送信者アドレスが拒否されました。サーバーからの応答は次のとおりです。521 mail not accepted from this domain と表示されます。 Exception e を発生させたのが、System.Reflection.TargetInvocationException で、 System.Reflection.TargetInvocationException を発生させたのが、 System.Runtime.InteropServices.COMException で、 COMException の発生元はない?・・・と、思うのですが勘違いしてますでしょうか? if (e is COMException ) { COMException ce = (COMException) e; Console.WriteLine("E: " + ce.InnerException); Console.WriteLine("E-Code: " + ce.ErrorCode); } とすると、 E: E-Code: -2147220978 と表示されました。 よろしくお願いします。m(_ _)m | ||||||||||||
|
投稿日時: 2004-06-28 19:17
メールの送信はSMTPMailクラスを使っているんですよね?
このクラスの概要にサンプルプログラムがあるのですが、そこではSystem.Web.HttpExceptionクラスで受けています。また、COMExceptionクラスの説明では、いくつかの例外種別については、クラス化された例外にマップされると書かれています。これから想像するに、エラーによって返ってくる例外が違うと思われます。したがって、すべてExceptionで受けて、COMExceptionかどうかの判定だけ行うのは、ちょっとしんどいかと。 メールサーバを立てられるなら、適当に設定して、考えられるパターンすべてをやってみて、どのような例外が返ってくるか見て、その上で対策を立てるのがよいかと。。。 今更な内容で申し訳ないですが。。。 |