2012-02-14 6 views
2

を使用しているとき、彼らはSmtpClient

を失敗した場合、私は電子メールを送信するループを作成したメールを送信私は、これが問題につながることができますように、コードでのThread.sleepを持っているベストプラクティスではありません読みました。しかし、メッセージが送信される前にトランザクションを廃棄するsmtpクライアントを使用しています。これをWebアプリケーションで使用する方がいいでしょうか?

using (var SmtpClient = new SmtpClient()) { 
    bool success = false; 
    int attemts = 0; 
    const int maxAttempts = 5; 
    do { 
     try { 
      SmtpClient.Send(mailMessage); 
      System.Threading.Thread.Sleep(400); 
      success = true; 
     } catch{ 
      // ok wait for request 
      success = false; 
      attemts ++; 
     } 
    } while (success && (attemts == maxAttempts)); 
} 
+0

コントローラーとそのほぼ完璧な結果が追加されました – cpoDesign

答えて

3

私はデニスの答えを補完したいです。

ここSendAsync方法で再試行回数パラメータは、使用することを可能にするSmtpClientラッパーの簡素化の実装:

public class EmailSender { 

    private int _currentRetryCount; 

    private int _maxRetryCount; 

    private MailMessage _mailMessage; 

    private bool _isAlreadyRun; 

    public event SendEmailCompletedEventHandler SendEmailCompleted; 

    public void SendEmailAsync(MailMessage message, int retryCount) { 

     if (_isAlreadyRun) { 
      throw new InvalidOperationException(
       "EmailSender doesn't support multiple concurrent invocations." 
      ); 
     } 

     _isAlreadyRun = true; 
     _maxRetryCount = retryCount; 
     _mailMessage = message; 

     SmtpClient client = new SmtpClient(); 
     client.SendCompleted += SmtpClientSendCompleted; 

     SendMessage(client); 
    } 

    private void SendMessage(SmtpClient client) { 
     try { 
      client.SendAsync(_mailMessage, Guid.NewGuid()); 
     } catch (Exception exception) { 
      EndProcessing(client); 
     } 
    } 

    private void EndProcessing (SmtpClient client) { 

     if (_mailMessage != null) { 
      _mailMessage.Dispose(); 
     } 

     if (client != null) { 
      client.SendCompleted -= SmtpClientSendCompleted; 
      client.Dispose(); 
     } 

     OnSendCompleted(
      new SendEmailCompletedEventArgs(null, false, null, _currentRetryCount) 
     ); 

     _isAlreadyRun = false; 
     _currentRetryCount = 0; 
    } 

    private void SmtpClientSendCompleted(object sender, AsyncCompletedEventArgs e) { 
     var smtpClient = (SmtpClient)sender; 

     if(e.Error == null || _currentRetryCount >= _maxRetryCount) { 
      EndProcessing(smtpClient); 
     } else { 
      _currentRetryCount++; 
      SendMessage(smtpClient); 
     } 
    } 

    protected virtual void OnSendCompleted(SendEmailCompletedEventArgs args) { 
     var handler = SendEmailCompleted; 
     if (handler != null) { 
      handler(this, args); 
     } 
    } 

} 


public delegate void SendEmailCompletedEventHandler(
    object sender, SendEmailCompletedEventArgs e); 

public class SendEmailCompletedEventArgs : AsyncCompletedEventArgs { 
    public SendEmailCompletedEventArgs(
     Exception error, 
     bool canceled, 
     object userState, 
     int retryCount) 
     : base(error, canceled, userState) { 
     RetryCount = retryCount; 
    } 

    public int RetryCount { get; set; } 
}} 

また以下は、消費者のコード例です:

 var sender = new EmailSender(); 

     sender.SendEmailCompleted += (o, eventArgs) 
      => Console.WriteLine(eventArgs.RetryCount); 

     sender.SendEmailAsync(new MailMessage(), 5); 

上のコードの断片には多くの単純化がありますが、主な考え方を理解する必要があります。

0

あなたは非同期SmtpClient.SendAsync()

を使用してメールを送信することができ、配信のためのSMTPサーバに指定した電子メールメッセージを送信します。このメソッドは、呼び出しスレッドをブロックせず、呼び出し側が、操作が完了したときに呼び出されるメソッドにオブジェクトを渡すことを許可します。 - MSDN

1

私はこの機能が必要な理由を正確にわからないんだけど、私はあなたの電子メールが送信されることを確認したいと仮定しています。

私の経験では、電子メールサーバー(またはサービス)が電子メールを処理するようにするのが最善です。電子メールサーバーは、永続的に成功または失敗するまで配信を再試行するように設計されています。ローカル(IISの組み込み電子メールサービスなど)または近く(ISPなど)の電子メールサーバーを選択すると、常に利用可能であることがほぼ保証されます。 SmtpClientに電子メールを送信するように設定します。サーバーが近くにいるので、アプリケーションの再試行の必要性を排除して、失敗する必要はなく、時間がかかりません。

いずれにしても、送信できなかった電子メールを記録するためにロギングを実装することをお勧めします。

0

あなたが考えるほど簡単ではありません。それは簡単に書くことができますが、実際に動作させることは難しいです:)。 あなたはこれを見てみることをお勧めしますSMTP Sender。私は自分の電子メール送信者を書き込もうとしていましたが、最終的にこの作業ライブラリを見つけました。私が問題を抱えていたものの1つは、ここで解決されたGMailで働いていたことです。私は何らかの形で著者に関連していませんが、私はこれを強く勧めます。

btw - そうですね、.Netはあなたのためにすべてを提供しており、外部の libを使用する理由はありませんが、数回試してみるとこのポストを覚えてお試しください。

+0

あなたのリンクは死んでいます... – Dave

関連する問題